PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/usr/share/doc/mailman-2.1.15/contrib/
Upload File :
Current File : //usr/share/doc/mailman-2.1.15/contrib/mmdsr
#!/bin/sh
###############################################################################
# mmdsr -- Mailman Daily Status Report (cron job, run at 23:59)
###############################################################################
# Copyright (c) 2005-2008 Brad Knowles
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 
#     Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 
#     Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer
#     in the documentation and/or other materials provided with the
#     distribution.
# 
#     The name of the author or other contributors may not be used
#     to endorse or promote products derived from this software without
#     specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
###############################################################################

###############################################################################
# Version history
###############################################################################
# 0.0.1		Initial creation by Brad Knowles <brad@stop.mail-abuse.org>
#		Created on: Tue Feb 15 04:01:20 PST 2005
#
# 0.0.2         Update by Brad Knowles <brad@stop.mail-abuse.org>
#               Updated on: Wed Feb 16 18:55:52 CET 2005
#               Feedback from Tom G. Christensen (tgc99):
#               > The current UID grab command doesn't work on Solaris 
#               > (2.6 & 8 tested).      
#               >
#               > I'd recommend this instead:
#               > ps -o user -p $$|tail -1
#               >
#               > This is tested and works on RH 6.2, RH 7.3, RHEL 2.1,
#               > RHEL3, FC3, FreeBSD 4.9, Solaris 2.6, 8.
#
# 0.0.3         Update by Brad Knowles <brad@stop.mail-abuse.org>
#               Updated on: Sun Mar 13 01:15:24 CET 2005
#               Noted errors from grep when trying to search a nonexistant
#               file.  Added "-s" option to compensate, and extra code to
#		notify the admin if the log file doesn't exist.
#
# 0.0.4         Update by Brad Knowles <brad@stop.mail-abuse.org>
#               Updated on: Sun Mar 13 01:58:37 CET 2005
#               Eliminate some extra cruft from the "fromusenet" logs.
#
# 0.0.5         Update by Brad Knowles <brad@stop.mail-abuse.org>
#               Updated on: Wed Apr 13 00:54:42 CEST 2005
#		Eliminate a lot of extra cruft from the "error" & "vette" logs.
#               Eliminate more cruft from the "fromusenet" logs.
#
# 0.0.6         Update by Brad Knowles <brad@stop.mail-abuse.org>
#               Updated on: Thu Apr 14 03:07:08 CEST 2005
#               Eliminate even more cruft from the "fromusenet" logs.
#               Eliminate more cruft from the "vette" logs.
#               Eliminate cruft from the "mischief" logs.
#
# 0.0.7         Update by Brad Knowles <brad@stop.mail-abuse.org>
#               Updated on: Sun May  1 22:29:13 CEST 2005   [guess]
#		The "error" log "no such list" errors didn't need to be
#		quite so "compressed", open them up to be more readable.
#		Also eliminate all use of "xargs", use "fmt -w 75" instead.
#
# 0.0.8         Update by Brad Knowles <brad@stop.mail-abuse.org>
#               Updated on: Sun May  1 23:09:13 CEST 2005
#		Clean up code for queue subdirectories to check.
#
# 0.0.9         Update by Brad Knowles <brad@stop.mail-abuse.org>
#               Updated on: Wed May 11 01:23:40 CEST 2005
#		Eliminate date/time stamps from the rest of the logs,
#		then pipe through `sort | uniq -c | sort -nr`
#		so that all possible duplicates are eliminated.
#
# 0.0.10	Update by Brad Knowles <brad@stop.mail-abuse.org>
#		Updated on: Tue Jul 12 16:53:49 CDT 2005
#		Add code to do summary of normal list activity
#
# 0.0.11	Update by Brad Knowles <brad@stop.mail-abuse.org>
#		Updated on: Tue Sep  6 15:44:19 CEST 2005
#		Tweaked display of Mailman/qfiles subdirectories
#		so as to avoid displaying more than $MAX_LINES
#		output, which really helps if you have thousands
#		of bounces sitting around, etc....
#		Also slightly tweaked display of fromusenet logs
#		to split summary from errors.
#
# 0.0.12	Update by Brad Knowles <brad@stop.mail-abuse.org>
#		Updated on: Thu Sep 22 22:37:35 CEST 2005
#		Bugs found by Mark Sapiro and Adrian Wells.
#		Mark suggested splitting the Mailman log directory
#		from the rest of the Mailman source and queues,
#		as well as making sure to clean up all temp files.
#		Adrian discovered that there was a log file format
#		change between Mailman 2.1.5 and 2.1.6, which broke
#		hourly statistics.
#
# 0.0.13	Update by Brad Knowles <brad@stop.mail-abuse.org>
#		Updated on: Mon Dec 26 05:54:27 CET 2005
#		Bugs found by Tom G. Christensen (tgc99):
#		> ps output on solaris is full of whitespace but a further
#		> echo get's rid of it.
#		> The lines in the smtp log are sometimes broken up by a
#		> newline (right before the msgid) which throws of the
#		> summary. Piping it through sed first will rejoin the broken
#		> lines.
#		> Use $AWK instead of awk.
#		Enhancements from Mark Sapiro:
#		> The vette log summary lists posts held for moderation
#		> individually under "Other Errors:". The following patch
#		> (watch out for wrapped lines) summarizes them by list instead.
#
# 0.0.14	Update by Brad Knowles <brad@stop.mail-abuse.org>
#		Updated on: Thu Dec 29 08:17:38 CET 2005
#		Added code to check /usr/local/mailman/data for
#		moderation hold queue
#
# 0.0.15	Update by Brad Knowles <brad@stop.mail-abuse.org>
#		Updated on: Thu Jan 26 02:39:38 CET 2006
#		Tweaked display of summary data in the "smtp-failure" log,
#		and "other" category in the "vette" log, so as to reduce
#		the spewage when things go wonky, mostly by removing
#		unique-ifying data like message-id or sender address.
#		Also tweaked moderation queue information, to tell us
#		how many Python pickle files are in the data directory,
#		as opposed to just doing a directory listing and skipping
#		the files in the middle if there are too many -- now we
#		know how many are being skipped.
#
# 0.0.16	Update by Brad Knowles <brad@stop.mail-abuse.org>
#		Updated on: Sun Jan 29 11:45:58 CET 2006
#		Mark found a couple of typos that I somehow let slip
#		through.  Thanks!
#
# 0.0.17	Update by Mark Sapiro <mark@msapiro.net>
#		Updated on: Thu Jan  3 18:25:06 PST 2008
#		Enabled processing the prior generation of a rotated log.
#		Added SORT_FIELD to the user modifiable parameters.
#
# 0.0.18	Update by Mark Sapiro <mark@msapiro.net>
#		Updated on: Tue May 13 08:58:26 PDT 2008
#		Changes for Mailman 2.1.10 --
#		Added 'bad' to the list of queues.
#		Made listing of a queue directory conditional on existence.
#		Sumarized unparseable messages and preserved queue entries
#		in the Other Errors section.
#
# 0.0.19	Update by Mark Sapiro <mark@msapiro.net>
#		Updated on: Sun Nov 30 10:26:15 PST 2008
#		Changed processing of fromusenet posts.  Previously, mmdsr
#		reported as gated only the first and last of a gated range.
#		Now mmdsr reports every post from the 'posted to' entries.
#
# 0.0.20	Update by Mark Sapiro <mark@msapiro.net>
#		Updated on: Sun Jul 26 08:56:41 PDT 2009
#		Added report of files in the preserved messages directory.
#
# 0.0.21	Update by Mark Sapiro <mark@msapiro.net>
#		Updated on: Sun Sep 27 12:45:44 PDT 2009
#		Refactored to use mktemp to create temp files

###############################################################################
# Set up locations of standard commands, directories, etc....
# You may need to modify these for your platform or installation.
###############################################################################

AWK="/usr/bin/awk"
BASENAME="/usr/bin/basename"
CAT="/bin/cat"
DATE="/bin/date"
EGREP="/bin/egrep"
FMT="/usr/bin/fmt"
GREP="/bin/grep"
HEAD="/usr/bin/head"
LS="/bin/ls"
MKTEMP="/bin/mktemp"
PS="/bin/ps"
RM="/bin/rm"
SED="/bin/sed"
SENDMAIL="/usr/sbin/sendmail"
SLEEP="/bin/sleep"
SORT="/usr/bin/sort"
TAIL="/usr/bin/tail"
TR="/usr/bin/tr"
UNIQ="/usr/bin/uniq"
XARGS="/usr/bin/xargs"
WC="/usr/bin/wc"

###############################################################################
# Arguments for your mktemp command to specify directory and/or create file.
# For example, HPUX mktemp requires "-c -d <dir>"; FreeBSD requires "-t <dir>".
###############################################################################
TMPDIR="-p /tmp"

###############################################################################
# Mailman queue directory
###############################################################################
QUEUEDIR="/usr/local/mailman/qfiles"

###############################################################################
# Mailman log directory
###############################################################################
LOGDIR="/usr/local/mailman/logs"

###############################################################################
# Mailman data directory
###############################################################################
DATADIR="/usr/local/mailman/data"

###############################################################################
# Mailman preserved messages directory
###############################################################################
SPAMDIR="/usr/local/mailman/spam"

###############################################################################
# Maximum number of subdirectory entries to display in report
###############################################################################
MAX_QUEUE_LINES=20

###############################################################################
# Maximum number of moderation queue pickle files to display in report
###############################################################################
MAX_DATA_LINES=100

###############################################################################
# Mailman Log files to check for errors.
# No need to specify path, only log file name.
###############################################################################
ERR_LOGS="error fromusenet locks mischief post qrunner smtp-failure vette"

###############################################################################
# Mailman Log files to summarize.
# No need to specify path, only log file name.
###############################################################################
SUM_LOGS="fromusenet post smtp"

###############################################################################
# Mailman queue subdirectories to check.  No need to specify path, only name.
###############################################################################
SUBDIRS="archive bad bounces commands in news out retry shunt virgin"

###############################################################################
# Specify the field specifier used by your sort command to select the second
# field.  This will normally be "+1" or "-k 2".
###############################################################################
SORT_FIELD="+1"

###############################################################################
# Specify recipients for report.  If none, then simply print to "STDOUT".
# Specify sender address for report.  Not used if recipient list is empty.
###############################################################################

SENDER="INSERT.YOUR.SENDER.ADDRESS@HERE"
RCPTS="INSERT.YOUR.RECIPIENTS.ADDRESSES@HERE"

###############################################################################
# If you run this program in cron at 23:59:00, you need to sleep sixty
# seconds to make sure that you capture all the logs for the previous day.
# Comment this line out to disable sleeping altogether.
###############################################################################

SLEEPTIME=60

###############################################################################
# What user id is Mailman installed under?
# How do we determine what UID this program is running as?
# NB:	There will probably be SysV vs. BSD semantic differences here.
#	Be careful.  Make sure the command you specify actually works.
#	The command string specified here may seem arcane, but should pull
#	out the information we need, and throw away everything else.  If
#	there is an easier cross-platform way to do it, please let me know.
###############################################################################

GRABUID=`$PS -o user -p $$ | $TAIL -1`
MYUID=`echo $GRABUID`
RUNAS="mailman"

###############################################################################
# No modifications below this line should be required.
###############################################################################

DAY=`$DATE '+%b %d'`
YEAR=`$DATE '+%Y'`

PROG=`$BASENAME $0`

if [ "${MYUID}" != "${RUNAS}" -a "${MYUID}" != "root" ] ; then
    echo "ERROR: You must be root or ${RUNAS} to run $PROG."
    exit 1
fi

if [ "${SLEEPTIME}" != "" -a "${RCPTS}x" != "${SENDER}x" ] ; then
    if [ $SLEEPTIME -gt 0 ] ; then
	$SLEEP $SLEEPTIME
    fi
fi

TMP=`$MKTEMP $TMPDIR`
TMPLOG=`$MKTEMP $TMPDIR`

if [ "${RCPTS}x" != "x" ] ; then
    echo "From: ${SENDER}" >> $TMP
    echo "To: ${RCPTS}" >> $TMP
    echo "Subject: Mailman Daily Status Report: $DAY $YEAR" >> $TMP
    echo "" >> $TMP
fi

echo "		Mailman Daily Status Report: $DAY $YEAR" >> $TMP
echo "" >> $TMP
echo "" >> $TMP

echo "******************************" >> $TMP
echo "Log File Summary" >> $TMP
echo "******************************" >> $TMP
echo "" >> $TMP

for LOG in $SUM_LOGS
do

    echo "Log file: $LOG" >> $TMP
    echo "==============================" >> $TMP

    if [ -f "$LOGDIR/${LOG}" ] ; then
      if [ -f "$LOGDIR/${LOG}.1" ] ; then
        $SED -e :a -e '$!N;s/\n //;ta' -e 'P;D' ${LOGDIR}/${LOG}.1 $LOGDIR/$LOG | $GREP -si "^$DAY [0-9][0-9:]* $YEAR" > $TMPLOG
      else
        $SED -e :a -e '$!N;s/\n //;ta' -e 'P;D' $LOGDIR/$LOG | $GREP -si "^$DAY [0-9][0-9:]* $YEAR" > $TMPLOG
      fi

	if [ "${LOG}" = "post" ] ; then

	    echo "" >> $TMP
	    echo "Hourly Summary of Posts" >> $TMP
	    echo "-----------------------" >> $TMP

	    $SED -e 's/^[A-Z][a-z][a-z] *[0-9]* //' -e 's/:.*$//' $TMPLOG | $UNIQ -c | $SORT -n $SORT_FIELD | $AWK '{ printf( "%8d  %02d:00-%02d:59\n", $1, $2, $2 ) }' >> $TMP

	    echo "" >> $TMP
	    echo "Post Count by List" >> $TMP
	    echo "------------------" >> $TMP

	    $SED -e 's/^.* post to //' -e 's/ .*$//' $TMPLOG | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Post Count by Sender" >> $TMP
	    echo "--------------------" >> $TMP

	    $SED -e 's/^.* from //' -e 's/,.*$//' $TMPLOG | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	elif [ "${LOG}" = "fromusenet" ] ; then

	    GRPS=`$EGREP -vi '(watermark:|nothing new| gating |: \[[0-9\.]*\])' $TMPLOG | $GREP -i ' posted to ' | $AWK '{ print $9 }' | $SED -e 's/:$//' | $SORT -u | $FMT -w 75`

	    for GRP in $GRPS
	    do
		echo "" >> $TMP
		echo "$GRP Article #'s Gated:" >> $TMP
		echo "------------------------------" >> $TMP
		$EGREP -vi '(watermark:|nothing new| gating |: \[[0-9\.]*\])' $TMPLOG | $GREP -i " posted to " | $GREP -i " $GRP: " | $AWK '{print $10}' |  $SORT -u | $FMT -w 75 >> $TMP
	    done

	elif [ "${LOG}" = "smtp" ] ; then

	    echo "" >> $TMP
	    echo "Hourly Summary of Messages Sent" >> $TMP
	    echo "-------------------------------" >> $TMP
	    $SED -e 's/^[A-Z][a-z][a-z] *[0-9]* //' -e 's/:.* for / /' -e 's/ recips,.*$//' $TMPLOG | $AWK '{ val=int($1); sum[val]+=$2 } END { for (i=0; i<24; i++) { printf "%8d %02d:00-%02d:59\n", sum[i], i, i } }' >> $TMP

	else

	    $SED 's/^.* ([0-9]*) //' $TMPLOG | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	fi

    else

    	echo " ### Log file ${LOG} does not exist ### " >> $TMP

    fi

    echo "" >> $TMP

done

echo "******************************" >> $TMP
echo "Log File Squawks" >> $TMP
echo "******************************" >> $TMP
echo "" >> $TMP

for LOG in $ERR_LOGS
do
    echo "Log file: $LOG" >> $TMP
    echo "==============================" >> $TMP

    if [ -f "$LOGDIR/${LOG}" ] ; then
      if [ -f "$LOGDIR/${LOG}.1" ] ; then
        $GREP -si "^$DAY [0-9][0-9:]* $YEAR" ${LOGDIR}/${LOG}.1 ${LOGDIR}/${LOG} | $SED "s/^[^:]*://" > $TMPLOG
      else
        $GREP -si "^$DAY [0-9][0-9:]* $YEAR" ${LOGDIR}/${LOG} > $TMPLOG
      fi

	if [ "${LOG}" = "error" ] ; then

	    echo "Uncaught Runner Exceptions:" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP 'Uncaught runner exception' $TMPLOG | $SED 's/^.*exception: //' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "No Such List:" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP 'No such list' $TMPLOG | $SED -e 's/^.* "//' -e 's/".*$//' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    CNT=`$GREP -i 'shunting' $TMPLOG | $WC -l`
	    if [ "${CNT}x" != "x" ] ; then
		if [ ${CNT} -gt 0 ] ; then
		    echo "" >> $TMP
		    echo "Shunting Count: $CNT" >> $TMP
		    echo "------------------------------" >> $TMP
		fi
	    fi

	    echo "" >> $TMP
	    echo "Other Errors:" >> $TMP
	    echo "------------------------------" >> $TMP
	    $EGREP -vi '(Uncaught runner exception|No such list|Traceback|shunting)' $TMPLOG | $SED -e 's/^.* ([0-9]*) //' -e 's/unparseable message.*/unparseable message/' -e 's/preserving file.*/preserving file/' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	elif [ "${LOG}" = "fromusenet" ] ; then

	    $EGREP -vi '(watermark:|nothing new| posted to |: \[[0-9\.]*\])' $TMPLOG | $GREP -vi " gating " | $SED 's/^.* ([0-9]*) //' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	elif [ "${LOG}" = "mischief" ] ; then

	    echo "" >> $TMP
	    echo "Login failure with private rosters (by user):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP -i 'Login failure with private rosters' $TMPLOG | $AWK '{ print $NF }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Unsub attempt of non-member (by user):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP -i 'Unsub attempt of non-member' $TMPLOG | $AWK '{ print $NF }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Reminder attempt of non-member (by user):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP -i 'Reminder attempt of non-member' $TMPLOG | $AWK '{ print $NF }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Other Messages:" >> $TMP
	    echo "------------------------------" >> $TMP
	    $EGREP -vi '(Login failure with private rosters|Unsub attempt of non-member|Reminder attempt of non-member)' $TMPLOG | $SED 's/^.* ([0-9]*) //' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	elif [ "${LOG}" = "post" ] ; then

	    $GREP -vi 'success' $TMPLOG | $SED 's/^.* ([0-9]*) //' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	elif [ "${LOG}" = "vette" ] ; then

	    echo "" >> $TMP
	    echo "Message held -- Post by non-member (by list):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP 'Post by non-member' $TMPLOG | $AWK '{ print $6 }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Message held -- Suspicious header (by list):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP -i 'suspicious header' $TMPLOG | $AWK '{ print $6 }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Discarded posting (by list):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP -i 'Discarded posting' $TMPLOG | $AWK '{ print $6 }' | $SED 's/:$//' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Bulk/Junk message discarded (by list):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $EGREP -i '(bulk|junk) message discarded' $TMPLOG | $AWK '{ print $NF }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Implicit destination (by list):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP -i 'Message has implicit destination' $TMPLOG | $AWK '{ print $6 }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Post to moderated newsgroup (by list):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP -i 'Posting to a moderated newsgroup' $TMPLOG | $AWK '{ print $6 }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Post to moderated list (by list):" >> $TMP
	    echo "------------------------------" >> $TMP
	    $GREP -i 'Post to moderated list' $TMPLOG | $AWK '{ print $6 }' | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	    echo "" >> $TMP
	    echo "Other Errors:" >> $TMP
	    echo "------------------------------" >> $TMP
	    $EGREP -vi '(Post by non-member|suspicious header|message approved|Discarded posting|bulk message discarded|junk message discarded|Message has implicit destination|Posting to a moderated newsgroup|Post to moderated list|Message discarded, msgid)' $TMPLOG | $SED -e 's/^.* ([0-9]*) //' -e 's/, message-id=<[^> ]*>:/:/' | $SORT | $UNIQ -c | $SORT -nr >> $TMP 

	elif [ "${LOG}" = "smtp-failure" ] ; then

	    $SED 's/^.* ([0-9]*) //' $TMPLOG | $SED 's/delivery to [^@ ]*@[^@ ]* failed with code/delivery failed with code/g' | $SORT | $UNIQ -c | $SORT -nr >> $TMP 

	else

	    $SED 's/^.* ([0-9]*) //' $TMPLOG | $SORT | $UNIQ -c | $SORT -nr >> $TMP

	fi
    else

    	echo " ### Log file ${LOG} does not exist ### " >> $TMP

    fi
    echo "" >> $TMP

done

echo "******************************" >> $TMP
echo "Queue Directory Contents" >> $TMP
echo "******************************" >> $TMP
echo "" >> $TMP

cd $QUEUEDIR
for DIR in $SUBDIRS
do

  if [ -d $DIR ] ; then
    $LS -la $DIR > $TMPLOG
    LINES=`$WC -l < $TMPLOG`
    LINES=`expr $LINES - 3`

    echo "Subdirectory: $DIR" >> $TMP
    echo "==============================" >> $TMP
    echo "Entries: $LINES" >> $TMP
    echo "------------------------------" >> $TMP

    if [ $LINES -le $MAX_QUEUE_LINES ] ; then
    	$CAT $TMPLOG >> $TMP
    else
    	$HEAD $TMPLOG >> $TMP
	echo "" >> $TMP
	echo "	More than $MAX_QUEUE_LINES total entries, skipping ..." >> $TMP
	echo "" >> $TMP
    	$TAIL $TMPLOG >> $TMP
    fi
    echo "" >> $TMP
  fi

done

echo "******************************" >> $TMP
echo "Data Directory Contents" >> $TMP
echo "	(Python pickle files only)" >> $TMP
echo "******************************" >> $TMP

cd $DATADIR

$LS -la | $GREP -i '\.pck$' > $TMPLOG
LINES=`$WC -l < $TMPLOG`

echo "Python pickle files: $LINES" >> $TMP
echo "==============================" >> $TMP
echo "" >> $TMP

if [ $LINES -le $MAX_DATA_LINES ] ; then
    $CAT $TMPLOG >> $TMP
else
    $HEAD $TMPLOG >> $TMP
    echo "" >> $TMP
    echo "	More than $MAX_DATA_LINES total entries, skipping ..." >> $TMP
    echo "" >> $TMP
    $TAIL $TMPLOG >> $TMP
fi
echo "" >> $TMP

echo "******************************" >> $TMP
echo "Moderation Queue Summary" >> $TMP
echo "******************************" >> $TMP
echo "" >> $TMP

$AWK '{ print $NF }' $TMPLOG | $GREP -i '^heldmsg-' | $SED -e 's/^heldmsg-//' -e 's/-[0-9]*\.pck$//' | $SORT | $UNIQ -c | $SORT -nr >> $TMP
echo "" >> $TMP

if [ -d $SPAMDIR ] ; then
    cd $SPAMDIR
    $LS -la | $GREP -i '\.msg$' > $TMPLOG
    LINES=`$WC -l < $TMPLOG`
    
    echo "******************************" >> $TMP
    echo "Preserved Messages Directory Contents" >> $TMP
    echo "        (.msg files only)" >> $TMP
    echo "******************************" >> $TMP
    echo "Files: $LINES" >> $TMP
    echo "==============================" >> $TMP
    echo "" >> $TMP
    
    if [ $LINES -le $MAX_DATA_LINES ] ; then
        $CAT $TMPLOG >> $TMP
    else
        $HEAD $TMPLOG >> $TMP
        echo "" >> $TMP
        echo "  More than $MAX_DATA_LINES total entries, skipping ..." >> $TMP
        echo "" >> $TMP
        $TAIL $TMPLOG >> $TMP
    fi
    echo "" >> $TMP
fi

###############################################################################
# Okay, we're done with all the code stuff, now handle the output
###############################################################################

if [ "${RCPTS}x" != "x" ] ; then
    $SENDMAIL -t -f$SENDER < $TMP
else
    $CAT $TMP
fi

$RM $TMP $TMPLOG