����JFIFXX�����    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222����"��4�� ���,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu���#ډb���_�N�?��wQ���5-�~�I���8����TK<5o�Iv-�����k�_U_�����~b�M��d����Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F�?_�'ϔ��_�Ջt��=||I ��6�έ"�����D���/[�k�9���Y�8ds|\���Ҿp6�Ҵ���]��.����6�z<�v��@]�i%��$j��~�g��J>��no����pM[me�i$[����s�o�ᘨ�˸ nɜG-�ĨU�ycP�3.DB�li�;��hj���x7Z^�N�h������N3u{�:j�x�힞��#M&��jL P@_���� P��&��o8������9�����@Sz6�t7#O�ߋ �s}Yf�T���lmr����Z)'N��k�۞p����w\�Tȯ?�8`�O��i{wﭹW�[�r�� ��Q4F�׊���3m&L�=��h3����z~��#�\�l :�F,j@�� ʱ�wQT����8�"kJO���6�֚l����}���R�>ډK���]��y����&����p�}b��;N�1�m�r$�|��7�>e�@B�TM*-iH��g�D�)� E�m�|�ؘbҗ�a��Ҿ����t4���o���G��*oCN�rP���Q��@z,|?W[0�����:�n,jWiE��W��$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S����VN;�}�s?.����� w�9��˟<���Mq4�Wv'��{)0�1mB��V����W[�����8�/<� �%���wT^�5���b��)iM� pg�N�&ݝ��VO~�q���u���9� ����!��J27����$O-���! �:�%H��� ـ����y�ΠM=t{!S�� oK8������t<����è:a������[�����ա�H���~��w��Qz`�po�^ ����Q��n� �,uu�C�$ ^���,������8�#��:�6��e�|~���!�3�3.�\0��q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�<���Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y�|�y��� ~�6�@c��1vOp�Ig����4��l�OD���L����� R���c���j�_�uX6��3?nk��Wy�f;^*B� ��@�~a�`��Eu������+���6�L��.ü>��}y���}_�O�6�͐�:�YrG�X��kG�����l^w���~㒶sy��Iu�!� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT��G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2��#I/�׍qz��^t�̔���b�Yz4x���t�){ OH��+(E��A&�N�������XT��o��"�XC��'���)}�J�z�p� ��~5�}�^����+�6����w��c��Q�|Lp�d�H��}�(�.|����k��c4^�"�����Z?ȕ ��a<�L�!039C� �Eu�C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf���M}7����]����s2tcS{�\icTx;�\��7K���P���ʇ Z O-��~��c>"��?�������P��E��O�8��@�8��G��Q�g�a�Վ���󁶠�䧘��_%#r�>�1�z�a��eb��qcPѵ��n���#L��� =��׀t� L�7�`��V���A{�C:�g���e@�w1 Xp3�c3�ġ����p��M"'-�@n4���fG��B3�DJ�8[Jo�ߐ���gK)ƛ��$���� ���8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`���?��K����QK�d����B`�s}�>���`��*�>��,*@J�d�oF*����弝��O}�k��s��]��y�ߘ��c1G�V���<=�7��7����6�q�PT��tXԀ�!9*4�4Tހ3XΛex�46���Y��D ����� �BdemDa����\�_l,��G�/���֌7���Y�](�xTt^%�GE�����4�}bT���ڹ�����;Y)���B�Q��u��>J/J �⮶.�XԄ��j�ݳ�+E��d ��r�5�_D�1 ��o�� �B�x�΢�#���<��W�����8���R6�@g�M�.��� dr�D��>(otU��@x=��~v���2� ӣ�d�oBd��3�eO�6�㣷�����ݜ6��6Y��Qz`��S��{���\P�~z m5{J/L��1������<�e�ͅPu�b�]�ϔ���'������f�b� Zpw��c`"��i���BD@:)ִ�:�]��hv�E�w���T�l��P���"Ju�}��وV J��G6��. J/�Qgl߭�e�����@�z�Zev2u�)]կ�����7x���s�M�-<ɯ�c��r�v�����@��$�ޮ}lk���a���'����>x��O\�ZFu>�����ck#��&:��`�$�ai�>2Δ����l���oF[h��lE�ܺ�Πk:)���`�� $[6�����9�����kOw�\|���8}������ބ:��񶐕��I�A1/�=�2[�,�!��.}gN#�u����b��� ~��݊��}34q����d�E��Lc��$��"�[q�U�硬g^��%B �z���r�pJ�ru%v\h1Y�ne`ǥ:g���pQM~�^�Xi� ��`S�:V29.�P���V�?B�k�� AEvw%�_�9C�Q����wKekPؠ�\�;Io d�{ ߞo�c1eP����\� `����E=���@K<�Y���eڼ�J���w����{av�F�'�M�@/J��+9p���|]�����Iw &`��8���&M�hg��[�{��Xj��%��Ӓ�$��(����ʹN���<>�I���RY���K2�NPlL�ɀ)��&e����B+ь����( � �JTx���_?EZ� }@ 6�U���뙢ط�z��dWI�n` D����噥�[��uV��"�G&Ú����2g�}&m��?ċ�"����Om#��������� ��{�ON��"S�X��Ne��ysQ���@Fn��Vg���dX�~nj�]J�<�K]:��FW��b�������62�=��5f����JKw��bf�X�55��~J �%^����:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v���g�8�1��f24;�V���ǔ�)����9���1\��c��v�/'Ƞ�w�������$�4�R-��t���� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃������A��20�c#��@ 0!1@AP"#2Q`$3V�%45a6�FRUq��� ����^7ׅ,$n�������+��F�`��2X'��0vM��p�L=������5��8������u�p~���.�`r�����\���O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;������S�T���1���i[U�ɵz�]��U)V�S6���3$K{�ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u�!��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� ���D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v�����멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$�JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4�[�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ�dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il��d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J��oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.���3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R=X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N�����#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%���JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$���L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����)�H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>�dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\�y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~������Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7��ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz��)�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!)'��8Ϣ�ٔ��ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'�L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���(}��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3�������QT��a����x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3�,#c�co��q�a)*Pt����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O���������m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l�O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m���PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q������~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~�|,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)`7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ����}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i����>J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0��Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q��nxҍ!U�f�!eh�i�2�m���`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{/ �?�͟��|1�:�#g��W�>$����d��J��d�B��=��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H����O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l����l�cGs�ځ�������y�Ac�����\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6����N6�q������N ! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td�� ?���N����a��3��m���C���w��������xA�m�q�m���m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4���r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0������u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ����V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G�����Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q�(v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9��3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M����A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#yw��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa����Q�#� WeF��ŮNj�p�J* mQ�N����*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]��陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv:��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WPw���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp�BGv[]�u�Ov���0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND��.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J �4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R��� ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`(�>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG��{+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/��*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�>e]�����Q�r�:����g�,i"�����ԩA�*M�<�G��b�if��l^M��5� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f�����֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ���˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)��h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~������ G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W�I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��BS�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c���]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪�\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W�����6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}�����6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@�P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6�����m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw�k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ����mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e��R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1[y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN��ĕ��0 !01@Q"2AaPq3BR������?���@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j�ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^���ԯ̾9Z��F��������n��1��� ��]�[��)�'������:�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ��&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0��;_��3 !01"@AQa2Pq#3BR������?��ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6����������4B>��o��](��$B���m�����a�!=��?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)����I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a�84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b��$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7��k�� 403WebShell
403Webshell
Server IP : 51.161.54.47  /  Your IP : 216.73.216.139
Web Server : Apache/2.4.68 (Unix) OpenSSL/1.1.1k
System : Linux host.ditinformatica.ar 4.18.0-553.144.1.el8_10.x86_64 #1 SMP Tue Jul 14 09:26:58 EDT 2026 x86_64
User : kalaycom ( 1021)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /usr/local/imap-2007f/lib/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/local/imap-2007f/lib/env_unix.c
/* ========================================================================
 * Copyright 1988-2008 University of Washington
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 
 * ========================================================================
 */

/*
 * Program:	UNIX environment routines
 *
 * Author:	Mark Crispin
 *		UW Technology
 *		University of Washington
 *		Seattle, WA  98195
 *		Internet: MRC@Washington.EDU
 *
 * Date:	1 August 1988
 * Last Edited:	23 February 2009
 */

#include <grp.h>
#include <signal.h>
#include <sys/wait.h>


/* in case stat.h is ancient */

#ifndef S_IRUSR
#define S_IRUSR S_IREAD
#endif
#ifndef S_IWUSR
#define S_IWUSR S_IWRITE
#endif
#ifndef S_IXUSR
#define S_IXUSR S_IEXEC
#endif
#ifndef S_IRGRP
#define S_IRGRP (S_IREAD >> 3)
#endif
#ifndef S_IWGRP
#define S_IWGRP (S_IWRITE >> 3)
#endif
#ifndef S_IXGRP
#define S_IXGRP (S_IEXEC >> 3)
#endif
#ifndef S_IROTH
#define S_IROTH (S_IREAD >> 6)
#endif
#ifndef S_IWOTH
#define S_IWOTH (S_IWRITE >> 6)
#endif
#ifndef S_IXOTH
#define S_IXOTH (S_IEXEC >> 6)
#endif

/* c-client environment parameters */

static char *myUserName = NIL;	/* user name */
static char *myHomeDir = NIL;	/* home directory name */
static char *myServerName = NIL;/* server name */
static char *myLocalHost = NIL;	/* local host name */
static char *myNewsrc = NIL;	/* newsrc file name */
static char *mailsubdir = NIL;	/* mailbox subdirectory name */
static char *sysInbox = NIL;	/* system inbox name */
static char *newsActive = NIL;	/* news active file */
static char *newsSpool = NIL;	/* news spool */
static char *blackBoxDir = NIL;	/* black box directory name */
				/* black box default home directory */
static char *blackBoxDefaultHome = NIL;
static char *sslCApath = NIL;	/* non-standard CA path */
static short anonymous = NIL;	/* is anonymous */
static short blackBox = NIL;	/* is a black box */
static short closedBox = NIL;	/* is a closed box (uses chroot() jail) */
static short restrictBox = NIL;	/* is a restricted box */
static short has_no_life = NIL;	/* is a cretin with no life */
				/* block environment init */
static short block_env_init = NIL;
static short hideDotFiles = NIL;/* hide files whose names start with . */
				/* advertise filesystem root */
static short advertisetheworld = NIL;
				/* only advertise own mailboxes and #shared */
static short limitedadvertise = NIL;
				/* disable automatic shared namespaces */
static short noautomaticsharedns = NIL;
static short no822tztext = NIL;	/* disable RFC [2]822 timezone text */
				/* client principals include service name */
static short kerb_cp_svr_name = NIL;
static long locktimeout = 5;	/* default lock timeout in minutes */
				/* default prototypes */
static MAILSTREAM *createProto = NIL;
static MAILSTREAM *appendProto = NIL;
				/* default user flags */
static char *userFlags[NUSERFLAGS] = {NIL};
static NAMESPACE *nslist[3];	/* namespace list */
static int logtry = 3;		/* number of server login tries */
				/* block notification */
static blocknotify_t mailblocknotify = mm_blocknotify;
				/* logout function */
static logouthook_t maillogouthook = NIL;
				/* logout data */
static void *maillogoutdata = NIL;
				/* allow user config files */
static short allowuserconfig = NIL;
				/* 1 = disable plaintext, 2 = if not SSL */
static long disablePlaintext = NIL;
static long list_max_level = 20;/* maximum level of list recursion */
				/* facility for syslog */
static int syslog_facility = LOG_MAIL;

/* Path of the privileged system lock program (mlock).  Normally set by
 * logic test.
 */

static char *lockpgm = LOCKPGM;

/* Directory used for shared locks.  MUST be the same for all users of the
 * system, and MUST be protected 1777.  /var/tmp may be preferable on some
 * systems.
 */

static const char *tmpdir = "/tmp";

/* Do not change shlock_mode.  Doing so can cause mailbox corruption and
 * denial of service.  It also defeats the entire purpose of the shared
 * lock mechanism.  The right way to avoid shared locks is to set up a
 * closed box (see the closedBox setting).
 */

				/* shared lock mode */
static const int shlock_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;


/* It is STRONGLY recommended that you do not change dotlock_mode.  Doing so
 * can cause denial of service with old dot-lock files left lying around.
 * However, since dot-locks are only used with traditional UNIX and MMDF
 * formats which are not normally shared, it is much less harmful to tamper
 * with this than with shlock_mode.
 */

				/* dot-lock mode */
static long dotlock_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;

/* File/directory access and protection policies */

/* Unlike shlock_mode, the ????_protection modes are intended to be fully
 * customizable according to site policy.  The values here are recommended
 * settings, based upon the documented purposes of the namespaces.
 */

	/* user space - only owner can read/write */
static char *myMailboxDir = NIL;/* user space directory name */
				/* default file protection */
static long mbx_protection = S_IRUSR|S_IWUSR;
				/* default directory protection */
static long dir_protection = S_IRUSR|S_IWUSR|S_IXUSR;

	/* user space for user "anonymous" */
				/* anonymous home directory */
static char *anonymousHome = NIL;

	/* #ftp - everybody can read, only owner can write */
static char *ftpHome = NIL;	/* ftp export home directory */
				/* default ftp file protection */
static long ftp_protection = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
static long ftp_dir_protection =/* default ftp directory protection */
  S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;

	/* #public - everybody can read/write */
static char *publicHome = NIL;	/* public home directory */
static long public_protection =	/* default public file protection */
  S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
				/* default public directory protection */
static long public_dir_protection =
  S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH;

	/* #shared/ - owner and group members can read/write */
static char *sharedHome = NIL;	/* shared home directory */
				/* default shared file protection */
static long shared_protection = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
				/* default shared directory protection */
static long shared_dir_protection =
  S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP;

/* OS bug workarounds - should be avoided at all cost */


/* Don't set fcntlhangbug unless you really have to, since it risks mailbox
 * corruption.  The flocksim.c mechanism is designed to detect NFS access
 * and no-op in that cases only, so this flag should be unnecessary.
 */

static short fcntlhangbug = NIL;/* flock() emulator using fcntl() is a no-op */


/* Don't set netfsstatbug unless you really have to, since it dramatically
 * slows down traditional UNIX and MMDF mailbox performance.
 */

static short netfsstatbug = NIL;/* compensate for broken stat() on network
				 * filesystems (AFS and old NFS)
				 */


/* Note: setting disableLockWarning means that you assert that the
 * so-modified copy of this software will NEVER be used:
 *  1) in conjunction with any software which expects .lock files
 *  2) to access NFS-mounted files and directories
 *
 * Unless both of these conditions apply, then do not set this flag.
 * Instead, read the FAQ (item 7.10) and either use 1777 protection
 * on the mail spool, or install mlock.
 *
 * In addition, by setting this flag you also agree that you are fully
 * legally and morally responsible when (not if) mail files are damaged
 * as the result of your choice.
 *
 * The mlock tool exists for a reason.  Use it.
 */
				/* disable warning if can't make .lock file */
static short disableLockWarning = NIL;

/* UNIX Namespaces */

				/* personal mh namespace */
static NAMESPACE nsmhf = {"#mh/",'/',NIL,NIL};
static NAMESPACE nsmh = {"#mhinbox",NIL,NIL,&nsmhf};
				/* home namespace */
static NAMESPACE nshome = {"",'/',NIL,&nsmh};
				/* UNIX other user namespace */
static NAMESPACE nsunixother = {"~",'/',NIL,NIL};
				/* black box other user namespace */
static NAMESPACE nsblackother = {"/",'/',NIL,NIL};
				/* public (anonymous OK) namespace */
static NAMESPACE nspublic = {"#public/",'/',NIL,NIL};
				/* netnews namespace */
static NAMESPACE nsnews = {"#news.",'.',NIL,&nspublic};
				/* FTP export namespace */
static NAMESPACE nsftp = {"#ftp/",'/',NIL,&nsnews};
				/* shared (no anonymous) namespace */
static NAMESPACE nsshared = {"#shared/",'/',NIL,&nsftp};
				/* world namespace */
static NAMESPACE nsworld = {"/",'/',NIL,&nsshared};
				/* only shared and public namespaces */
static NAMESPACE nslimited = {"#shared/",'/',NIL,&nspublic};



#include "write.c"		/* include safe writing routines */
#include "crexcl.c"		/* include exclusive create */
#include "pmatch.c"		/* include wildcard pattern matcher */

/* Get all authenticators */

#include "auths.c"

/* Environment manipulate parameters
 * Accepts: function code
 *	    function-dependent value
 * Returns: function-dependent return value
 */

void *env_parameters (long function,void *value)
{
  void *ret = NIL;
  switch ((int) function) {
  case GET_NAMESPACE:
    ret = (void *) nslist;
    break;
  case SET_USERNAME:
    if (myUserName) fs_give ((void **) &myUserName);
    myUserName = cpystr ((char *) value);
  case GET_USERNAME:
    ret = (void *) myUserName;
    break;
  case SET_HOMEDIR:
    if (myHomeDir) fs_give ((void **) &myHomeDir);
    myHomeDir = cpystr ((char *) value);
  case GET_HOMEDIR:
    ret = (void *) myHomeDir;
    break;
  case SET_LOCALHOST:
    if (myLocalHost) fs_give ((void **) &myLocalHost);
    myLocalHost = cpystr ((char *) value);
  case GET_LOCALHOST:
    ret = (void *) myLocalHost;
    break;
  case SET_NEWSRC:
    if (myNewsrc) fs_give ((void **) &myNewsrc);
    myNewsrc = cpystr ((char *) value);
  case GET_NEWSRC:
    ret = (void *) myNewsrc;
    break;
  case SET_NEWSACTIVE:
    if (newsActive) fs_give ((void **) &newsActive);
    newsActive = cpystr ((char *) value);
  case GET_NEWSACTIVE:
    ret = (void *) newsActive;
    break;
  case SET_NEWSSPOOL:
    if (newsSpool) fs_give ((void **) &newsSpool);
    newsSpool = cpystr ((char *) value);
  case GET_NEWSSPOOL:
    ret = (void *) newsSpool;
    break;

  case SET_ANONYMOUSHOME:
    if (anonymousHome) fs_give ((void **) &anonymousHome);
    anonymousHome = cpystr ((char *) value);
  case GET_ANONYMOUSHOME:
    if (!anonymousHome) anonymousHome = cpystr (ANONYMOUSHOME);
    ret = (void *) anonymousHome;
    break;
  case SET_FTPHOME:
    if (ftpHome) fs_give ((void **) &ftpHome);
    ftpHome = cpystr ((char *) value);
  case GET_FTPHOME:
    ret = (void *) ftpHome;
    break;
  case SET_PUBLICHOME:
    if (publicHome) fs_give ((void **) &publicHome);
    publicHome = cpystr ((char *) value);
  case GET_PUBLICHOME:
    ret = (void *) publicHome;
    break;
  case SET_SHAREDHOME:
    if (sharedHome) fs_give ((void **) &sharedHome);
    sharedHome = cpystr ((char *) value);
  case GET_SHAREDHOME:
    ret = (void *) sharedHome;
    break;
  case SET_SYSINBOX:
    if (sysInbox) fs_give ((void **) &sysInbox);
    sysInbox = cpystr ((char *) value);
  case GET_SYSINBOX:
    ret = (void *) sysInbox;
    break;
  case SET_SSLCAPATH:		/* this can be set null */
    if (sslCApath) fs_give ((void **) &sslCApath);
    sslCApath = value ? cpystr ((char *) value) : value;
    break;
  case GET_SSLCAPATH:
    ret = (void *) sslCApath;
    break;
  case SET_LISTMAXLEVEL:
    list_max_level = (long) value;
  case GET_LISTMAXLEVEL:
    ret = (void *) list_max_level;
    break;

  case SET_MBXPROTECTION:
    mbx_protection = (long) value;
  case GET_MBXPROTECTION:
    ret = (void *) mbx_protection;
    break;
  case SET_DIRPROTECTION:
    dir_protection = (long) value;
  case GET_DIRPROTECTION:
    ret = (void *) dir_protection;
    break;
  case SET_LOCKPROTECTION:
    dotlock_mode = (long) value;
  case GET_LOCKPROTECTION:
    ret = (void *) dotlock_mode;
    break;
  case SET_FTPPROTECTION:
    ftp_protection = (long) value;
  case GET_FTPPROTECTION:
    ret = (void *) ftp_protection;
    break;
  case SET_PUBLICPROTECTION:
    public_protection = (long) value;
  case GET_PUBLICPROTECTION:
    ret = (void *) public_protection;
    break;
  case SET_SHAREDPROTECTION:
    shared_protection = (long) value;
  case GET_SHAREDPROTECTION:
    ret = (void *) shared_protection;
    break;
  case SET_FTPDIRPROTECTION:
    ftp_dir_protection = (long) value;
  case GET_FTPDIRPROTECTION:
    ret = (void *) ftp_dir_protection;
    break;
  case SET_PUBLICDIRPROTECTION:
    public_dir_protection = (long) value;
  case GET_PUBLICDIRPROTECTION:
    ret = (void *) public_dir_protection;
    break;
  case SET_SHAREDDIRPROTECTION:
    shared_dir_protection = (long) value;
  case GET_SHAREDDIRPROTECTION:
    ret = (void *) shared_dir_protection;
    break;

  case SET_LOCKTIMEOUT:
    locktimeout = (long) value;
  case GET_LOCKTIMEOUT:
    ret = (void *) locktimeout;
    break;
  case SET_DISABLEFCNTLLOCK:
    fcntlhangbug = value ? T : NIL;
  case GET_DISABLEFCNTLLOCK:
    ret = (void *) (fcntlhangbug ? VOIDT : NIL);
    break;
  case SET_LOCKEACCESERROR:
    disableLockWarning = value ? NIL : T;
  case GET_LOCKEACCESERROR:
    ret = (void *) (disableLockWarning ? NIL : VOIDT);
    break;
  case SET_HIDEDOTFILES:
    hideDotFiles = value ? T : NIL;
  case GET_HIDEDOTFILES:
    ret = (void *) (hideDotFiles ? VOIDT : NIL);
    break;
  case SET_DISABLEPLAINTEXT:
    disablePlaintext = (long) value;
  case GET_DISABLEPLAINTEXT:
    ret = (void *) disablePlaintext;
    break;
  case SET_CHROOTSERVER:
    closedBox = value ? T : NIL;
  case GET_CHROOTSERVER:
    ret = (void *) (closedBox ? VOIDT : NIL);
    break;
  case SET_ADVERTISETHEWORLD:
    advertisetheworld = value ? T : NIL;
  case GET_ADVERTISETHEWORLD:
    ret = (void *) (advertisetheworld ? VOIDT : NIL);
    break;
  case SET_LIMITEDADVERTISE:
    limitedadvertise = value ? T : NIL;
  case GET_LIMITEDADVERTISE:
    ret = (void *) (limitedadvertise ? VOIDT : NIL);
    break;
  case SET_DISABLEAUTOSHAREDNS:
    noautomaticsharedns = value ? T : NIL;
  case GET_DISABLEAUTOSHAREDNS:
    ret = (void *) (noautomaticsharedns ? VOIDT : NIL);
    break;
  case SET_DISABLE822TZTEXT:
    no822tztext = value ? T : NIL;
  case GET_DISABLE822TZTEXT:
    ret = (void *) (no822tztext ? VOIDT : NIL);
    break;

  case SET_USERHASNOLIFE:
    has_no_life = value ? T : NIL;
  case GET_USERHASNOLIFE:
    ret = (void *) (has_no_life ? VOIDT : NIL);
    break;
  case SET_KERBEROS_CP_SVR_NAME:
    kerb_cp_svr_name = value ? T : NIL;
  case GET_KERBEROS_CP_SVR_NAME:
    ret = (void *) (kerb_cp_svr_name ? VOIDT : NIL);
    break;
  case SET_NETFSSTATBUG:
    netfsstatbug = value ? T : NIL;
  case GET_NETFSSTATBUG:
    ret = (void *) (netfsstatbug ? VOIDT : NIL);
    break;
  case SET_BLOCKENVINIT:
    block_env_init = value ? T : NIL;
  case GET_BLOCKENVINIT:
    ret = (void *) (block_env_init ? VOIDT : NIL);
    break;
  case SET_BLOCKNOTIFY:
    mailblocknotify = (blocknotify_t) value;
  case GET_BLOCKNOTIFY:
    ret = (void *) mailblocknotify;
    break;
  case SET_LOGOUTHOOK:
    maillogouthook = (logouthook_t) value;
  case GET_LOGOUTHOOK:
    ret = maillogouthook;
    break;
  case SET_LOGOUTDATA:
    maillogoutdata = (void *) value;
  case GET_LOGOUTDATA:
    ret = maillogoutdata;
  }
  return ret;
}

/* Write current time
 * Accepts: destination string
 *	    optional format of day-of-week prefix
 *	    format of date and time
 *	    flag whether to append symbolic timezone
 */

static void do_date (char *date,char *prefix,char *fmt,int suffix)
{
  time_t tn = time (0);
  struct tm *t = gmtime (&tn);
  int zone = t->tm_hour * 60 + t->tm_min;
  int julian = t->tm_yday;
  t = localtime (&tn);		/* get local time now */
				/* minus UTC minutes since midnight */
  zone = t->tm_hour * 60 + t->tm_min - zone;
  /* julian can be one of:
   *  36x  local time is December 31, UTC is January 1, offset -24 hours
   *    1  local time is 1 day ahead of UTC, offset +24 hours
   *    0  local time is same day as UTC, no offset
   *   -1  local time is 1 day behind UTC, offset -24 hours
   * -36x  local time is January 1, UTC is December 31, offset +24 hours
   */
  if (julian = t->tm_yday -julian)
    zone += ((julian < 0) == (abs (julian) == 1)) ? -24*60 : 24*60;
  if (prefix) {			/* want day of week? */
    sprintf (date,prefix,days[t->tm_wday]);
    date += strlen (date);	/* make next sprintf append */
  }
				/* output the date */
  sprintf (date,fmt,t->tm_mday,months[t->tm_mon],t->tm_year+1900,
	   t->tm_hour,t->tm_min,t->tm_sec,zone/60,abs (zone) % 60);
				/* append timezone suffix if desired */
  if (suffix) rfc822_timezone (date,(void *) t);
}

/* Write current time in RFC 822 format
 * Accepts: destination string
 */

void rfc822_date (char *date)
{
  do_date (date,"%s, ","%d %s %d %02d:%02d:%02d %+03d%02d",
	   no822tztext ? NIL : T);
}


/* Write current time in fixed-width RFC 822 format
 * Accepts: destination string
 */

void rfc822_fixed_date (char *date)
{
  do_date (date,NIL,"%02d %s %4d %02d:%02d:%02d %+03d%02d",NIL);
}


/* Write current time in internal format
 * Accepts: destination string
 */

void internal_date (char *date)
{
  do_date (date,NIL,"%02d-%s-%d %02d:%02d:%02d %+03d%02d",NIL);
}

/* Initialize server
 * Accepts: server name for syslog or NIL
 *	    /etc/services service name or NIL
 *	    alternate /etc/services service name or NIL
 *	    clock interrupt handler
 *	    kiss-of-death interrupt handler
 *	    hangup interrupt handler
 *	    termination interrupt handler
 */

void server_init (char *server,char *service,char *sslservice,
		  void *clkint,void *kodint,void *hupint,void *trmint,
		  void *staint)
{
  int onceonly = server && service && sslservice;
  if (onceonly) {		/* set server name in syslog */
    int mask;
    openlog (myServerName = cpystr (server),LOG_PID,syslog_facility);
    fclose (stderr);		/* possibly save a process ID */
    dorc (NIL,NIL);		/* do systemwide configuration */
    switch (mask = umask (022)){/* check old umask */
    case 0:			/* definitely unreasonable */
    case 022:			/* don't need to change it */
      break;
    default:			/* already was a reasonable value */
      umask (mask);		/* so change it back */
    }
  }
  arm_signal (SIGALRM,clkint);	/* prepare for clock interrupt */
  arm_signal (SIGUSR2,kodint);	/* prepare for Kiss Of Death */
  arm_signal (SIGHUP,hupint);	/* prepare for hangup */
  arm_signal (SIGPIPE,hupint);	/* alternative hangup */
  arm_signal (SIGTERM,trmint);	/* prepare for termination */
				/* status dump */
  if (staint) arm_signal (SIGUSR1,staint);
  if (onceonly) {		/* set up network and maybe SSL */
    long port;
    struct servent *sv;
    /* Use SSL if SSL service, or if server starts with "s" and not service */
    if (((port = tcp_serverport ()) >= 0)) {
      if ((sv = getservbyname (service,"tcp")) && (port == ntohs (sv->s_port)))
	syslog (LOG_DEBUG,"%s service init from %s",service,tcp_clientaddr ());
      else if ((sv = getservbyname (sslservice,"tcp")) &&
	       (port == ntohs (sv->s_port))) {
	syslog (LOG_DEBUG,"%s SSL service init from %s",sslservice,
		tcp_clientaddr ());
	ssl_server_init (server);
      }
      else {			/* not service or SSL service port */
	syslog (LOG_DEBUG,"port %ld service init from %s",port,
		tcp_clientaddr ());
	if (*server == 's') ssl_server_init (server);
      }
    }
  }
}

/* Wait for stdin input
 * Accepts: timeout in seconds
 * Returns: T if have input on stdin, else NIL
 */

long server_input_wait (long seconds)
{
  fd_set rfd,efd;
  struct timeval tmo;
  FD_ZERO (&rfd);
  FD_ZERO (&efd);
  FD_SET (0,&rfd);
  FD_SET (0,&efd);
  tmo.tv_sec = seconds; tmo.tv_usec = 0;
  return select (1,&rfd,0,&efd,&tmo) ? LONGT : NIL;
}

/* Return UNIX password entry for user name
 * Accepts: user name string
 * Returns: password entry
 *
 * Tries all-lowercase form of user name if given user name fails
 */

static struct passwd *pwuser (unsigned char *user)
{
  unsigned char *s;
  struct passwd *pw = getpwnam (user);
  if (!pw) {			/* failed, see if any uppercase characters */
    for (s = user; *s && ((*s < 'A') || (*s > 'Z')); s++);
    if (*s) {			/* yes, try all lowercase form */
      pw = getpwnam (s = lcase (cpystr (user)));
      fs_give ((void **) &s);
    }
  }
  return pw;
}


/* Validate password for user name
 * Accepts: user name string
 *	    password string
 *	    argument count
 *	    argument vector
 * Returns: password entry if validated
 *
 * Tries password+1 if password fails and starts with space
 */

static struct passwd *valpwd (char *user,char *pwd,int argc,char *argv[])
{
  char *s;
  struct passwd *pw;
  struct passwd *ret = NIL;
  if (auth_md5.server) {	/* using CRAM-MD5 authentication? */
    if (s = auth_md5_pwd (user)) {
      if (!strcmp (s,pwd) || ((*pwd == ' ') && pwd[1] && !strcmp (s,pwd+1)))
	ret = pwuser (user);	/* validated, get passwd entry for user */
      memset (s,0,strlen (s));	/* erase sensitive information */
      fs_give ((void **) &s);
    }
  }
  else if (pw = pwuser (user)) {/* can get user? */
    s = cpystr (pw->pw_name);	/* copy returned name in case we need it */
    if (*pwd && !(ret = checkpw (pw,pwd,argc,argv)) &&
	(*pwd == ' ') && pwd[1] && (ret = pwuser (s)))
      ret = checkpw (pw,pwd+1,argc,argv);
    fs_give ((void **) &s);	/* don't need copy of name any more */
  }
  return ret;
}

/* Server log in
 * Accepts: user name string
 *	    password string
 *	    authenticating user name string
 *	    argument count
 *	    argument vector
 * Returns: T if password validated, NIL otherwise
 */

long server_login (char *user,char *pwd,char *authuser,int argc,char *argv[])
{
  struct passwd *pw = NIL;
  int level = LOG_NOTICE;
  char *err = "failed";
				/* cretins still haven't given up */
  if ((strlen (user) >= NETMAXUSER) ||
      (authuser && (strlen (authuser) >= NETMAXUSER))) {
    level = LOG_ALERT;		/* escalate this alert */
    err = "SYSTEM BREAK-IN ATTEMPT";
    logtry = 0;			/* render this session useless */
  }
  else if (logtry-- <= 0) err = "excessive login failures";
  else if (disablePlaintext) err = "disabled";
  else if (!(authuser && *authuser)) pw = valpwd (user,pwd,argc,argv);
  else if (valpwd (authuser,pwd,argc,argv)) pw = pwuser (user);
  if (pw && pw_login (pw,authuser,pw->pw_name,NIL,argc,argv)) return T;
  syslog (level|LOG_AUTH,"Login %s user=%.64s auth=%.64s host=%.80s",err,
	  user,(authuser && *authuser) ? authuser : user,tcp_clienthost ());
  sleep (3);			/* slow down possible cracker */
  return NIL;
}

/* Authenticated server log in
 * Accepts: user name string
 *	    authenticating user name string
 *	    argument count
 *	    argument vector
 * Returns: T if password validated, NIL otherwise
 */

long authserver_login (char *user,char *authuser,int argc,char *argv[])
{
  return pw_login (pwuser (user),authuser,user,NIL,argc,argv);
}


/* Log in as anonymous daemon
 * Accepts: argument count
 *	    argument vector
 * Returns: T if successful, NIL if error
 */

long anonymous_login (int argc,char *argv[])
{
				/* log in Mr. A. N. Onymous */
  return pw_login (getpwnam (ANONYMOUSUSER),NIL,NIL,
		   (char *) mail_parameters (NIL,GET_ANONYMOUSHOME,NIL),
		   argc,argv);
}

/* Finish log in and environment initialization
 * Accepts: passwd struct for loginpw()
 *	    optional authentication user name
 *	    user name (NIL for anonymous)
 *	    home directory (NIL to use directory from passwd struct)
 *	    argument count
 *	    argument vector
 * Returns: T if successful, NIL if error
 */

long pw_login (struct passwd *pw,char *auser,char *user,char *home,int argc,
	       char *argv[])
{
  struct group *gr;
  char **t;
  long ret = NIL;
  if (pw && pw->pw_uid) {	/* must have passwd struct for non-UID 0 */
				/* make safe copies of user and home */
    if (user) user = cpystr (pw->pw_name);
    home = cpystr (home ? home : pw->pw_dir);
				/* authorization ID .NE. authentication ID? */
    if (user && auser && *auser && compare_cstring (auser,user)) {
				/* scan list of mail administrators */
      if ((gr = getgrnam (ADMINGROUP)) && (t = gr->gr_mem)) while (*t && !ret)
	if (!compare_cstring (auser,*t++))
	  ret = pw_login (pw,NIL,user,home,argc,argv);
      syslog (LOG_NOTICE|LOG_AUTH,"%s %.80s override of user=%.80s host=%.80s",
	      ret ? "Admin" : "Failed",auser,user,tcp_clienthost ());
    }
    else if (closedBox) {	/* paranoid site, lock out other directories */
      if (chdir (home) || chroot (home))
	syslog (LOG_NOTICE|LOG_AUTH,
		"Login %s failed: unable to set chroot=%.80s host=%.80s",
		pw->pw_name,home,tcp_clienthost ());
      else if (loginpw (pw,argc,argv)) ret = env_init (user,NIL);
      else fatal ("Login failed after chroot");
    }
				/* normal login */
    else if (((pw->pw_uid == geteuid ()) || loginpw (pw,argc,argv)) &&
	     (ret = env_init (user,home))) chdir (myhomedir ());
    fs_give ((void **) &home);	/* clean up */
    if (user) fs_give ((void **) &user);
  }
  endpwent ();			/* in case shadow passwords in pw data */
  return ret;			/* return status */
}

/* Initialize environment
 * Accepts: user name (NIL for anonymous)
 *	    home directory name
 * Returns: T, always
 */

long env_init (char *user,char *home)
{
  extern MAILSTREAM CREATEPROTO;
  extern MAILSTREAM EMPTYPROTO;
  struct passwd *pw;
  struct stat sbuf;
  char tmp[MAILTMPLEN];
				/* don't init if blocked */
  if (block_env_init) return LONGT;
  if (myUserName) fatal ("env_init called twice!");
				/* initially nothing in namespace list */
  nslist[0] = nslist[1] = nslist[2] = NIL;
				/* myUserName must be set before dorc() call */
  myUserName = cpystr (user ? user : ANONYMOUSUSER);
				/* force default prototypes to be set */
  if (!createProto) createProto = &CREATEPROTO;
  if (!appendProto) appendProto = &EMPTYPROTO;
  dorc (NIL,NIL);		/* do systemwide configuration */
  if (!home) {			/* closed box server */
				/* standard user can only reference home */
    if (user) nslist[0] = &nshome;
    else {			/* anonymous user */
      nslist[0] = &nsblackother; /* set root */
      anonymous = T;		/* flag as anonymous */
    }
    myHomeDir = cpystr ("");	/* home directory is root */
    sysInbox = cpystr ("INBOX");/* make system INBOX */
  }
  else {			/* open or black box */
    closedBox = NIL;		/* definitely not a closed box */
    if (user) {			/* remember user name and home directory */
      if (blackBoxDir) {	/* build black box directory name */
	sprintf (tmp,"%s/%s",blackBoxDir,myUserName);
				/* must exist */
	if (!((!stat (home = tmp,&sbuf) && (sbuf.st_mode & S_IFDIR)) ||
	      (blackBoxDefaultHome &&
	       !stat (home = blackBoxDefaultHome,&sbuf) &&
	       (sbuf.st_mode & S_IFDIR)))) fatal ("no home");
	sysInbox = (char *) fs_get (strlen (home) + 7);
				/* set system INBOX */
	sprintf (sysInbox,"%s/INBOX",home);
	blackBox = T;		/* mark that it's a black box */
				/* mbox meaningless if black box */
	mail_parameters (NIL,DISABLE_DRIVER,(void *) "mbox");
      }
      nslist[0] = &nshome;	/* home namespace */
				/* limited advertise namespaces */
      if (limitedadvertise) nslist[2] = &nslimited;
      else if (blackBox) {	/* black box namespaces */
	nslist[1] = &nsblackother;
	nslist[2] = &nsshared;
      }
      else {			/* open box namespaces */
	nslist[1] = &nsunixother;
	nslist[2] = advertisetheworld ? &nsworld : &nsshared;
      }
    }
    else {
      nslist[2] = &nsftp;	/* anonymous user */
      sprintf (tmp,"%s/INBOX",
	       home = (char *) mail_parameters (NIL,GET_ANONYMOUSHOME,NIL));
      sysInbox = cpystr (tmp);	/* make system INBOX */
      anonymous = T;		/* flag as anonymous */
    }
    myHomeDir = cpystr (home);	/* set home directory */
  }

  if (allowuserconfig) {	/* allow user config files */
    dorc (strcat (strcpy (tmp,myHomeDir),"/.mminit"),T);
    dorc (strcat (strcpy (tmp,myHomeDir),"/.imaprc"),NIL);
  }
  if (!closedBox && !noautomaticsharedns) {
				/* #ftp namespace */
    if (!ftpHome && (pw = getpwnam ("ftp"))) ftpHome = cpystr (pw->pw_dir);
				/* #public namespace */
    if (!publicHome && (pw = getpwnam ("imappublic")))
      publicHome = cpystr (pw->pw_dir);
				/* #shared namespace */
    if (!anonymous && !sharedHome && (pw = getpwnam ("imapshared")))
      sharedHome = cpystr (pw->pw_dir);
  }
  if (!myLocalHost) mylocalhost ();
  if (!myNewsrc) myNewsrc = cpystr(strcat (strcpy (tmp,myHomeDir),"/.newsrc"));
  if (!newsActive) newsActive = cpystr (ACTIVEFILE);
  if (!newsSpool) newsSpool = cpystr (NEWSSPOOL);
				/* re-do open action to get flags */
  (*createProto->dtb->open) (NIL);
  endpwent ();			/* close pw database */
  return T;
}
 
/* Return my user name
 * Accepts: pointer to optional flags
 * Returns: my user name
 */

char *myusername_full (unsigned long *flags)
{
  struct passwd *pw;
  struct stat sbuf;
  char *s;
  unsigned long euid;
  char *ret = UNLOGGEDUSER;
				/* no user name yet and not root? */
  if (!myUserName && (euid = geteuid ())) {
				/* yes, look up getlogin() user name or EUID */
    if (((s = (char *) getlogin ()) && *s && (strlen (s) < NETMAXUSER) &&
	 (pw = getpwnam (s)) && (pw->pw_uid == euid)) ||
	(pw = getpwuid (euid))) {
      if (block_env_init) {	/* don't env_init if blocked */
	if (flags) *flags = MU_LOGGEDIN;
	return pw->pw_name;
      }
      env_init (pw->pw_name,
		((s = getenv ("HOME")) && *s && (strlen (s) < NETMAXMBX) &&
		 !stat (s,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFDIR)) ?
		s : pw->pw_dir);
    }
    else fatal ("Unable to look up user name");
  }
  if (myUserName) {		/* logged in? */
    if (flags) *flags = anonymous ? MU_ANONYMOUS : MU_LOGGEDIN;
    ret = myUserName;		/* return user name */
  }
  else if (flags) *flags = MU_NOTLOGGEDIN;
  return ret;
}


/* Return my local host name
 * Returns: my local host name
 */

char *mylocalhost ()
{
  if (!myLocalHost) {
    char *s,tmp[MAILTMPLEN];
    char *t = "unknown";
    tmp[0] = tmp[MAILTMPLEN-1] = '\0';
    if (!gethostname (tmp,MAILTMPLEN-1) && tmp[0]) {
				/* sanity check of name */
      for (s = tmp; (*s > 0x20) && (*s < 0x7f); ++s);
      if (!*s) t = tcp_canonical (tmp);
    }
    myLocalHost = cpystr (t);
  }
  return myLocalHost;
}

/* Return my home directory name
 * Returns: my home directory name
 */

char *myhomedir ()
{
  if (!myHomeDir) myusername ();/* initialize if first time */
  return myHomeDir ? myHomeDir : "";
}


/* Return my home mailbox name
 * Returns: my home directory name
 */

static char *mymailboxdir ()
{
  char *home = myhomedir ();
				/* initialize if first time */
  if (!myMailboxDir && myHomeDir) {
    if (mailsubdir) {
      char tmp[MAILTMPLEN];
      sprintf (tmp,"%s/%s",home,mailsubdir);
      myMailboxDir = cpystr (tmp);/* use pre-defined subdirectory of home */
    }
    else myMailboxDir = cpystr (home);
  }
  return myMailboxDir ? myMailboxDir : "";
}


/* Return system standard INBOX
 * Accepts: buffer string
 */

char *sysinbox ()
{
  char tmp[MAILTMPLEN];
  if (!sysInbox) {		/* initialize if first time */
    sprintf (tmp,"%s/%s",MAILSPOOL,myusername ());
    sysInbox = cpystr (tmp);	/* system inbox is from mail spool */
  }
  return sysInbox;
}

/* Return mailbox directory name
 * Accepts: destination buffer
 *	    directory prefix
 *	    name in directory
 * Returns: file name or NIL if error
 */

char *mailboxdir (char *dst,char *dir,char *name)
{
  char tmp[MAILTMPLEN];
  if (dir || name) {		/* if either argument provided */
    if (dir) {
      if (strlen (dir) > NETMAXMBX) return NIL;
      strcpy (tmp,dir);		/* write directory prefix */
    }
    else tmp[0] = '\0';		/* otherwise null string */
    if (name) {
      if (strlen (name) > NETMAXMBX) return NIL;
      strcat (tmp,name);	/* write name in directory */
    }
				/* validate name, return its name */
    if (!mailboxfile (dst,tmp)) return NIL;
  }
				/* no arguments, wants mailbox directory */
  else strcpy (dst,mymailboxdir ());
  return dst;			/* return the name */
}

/* Return mailbox file name
 * Accepts: destination buffer
 *	    mailbox name
 * Returns: file name or empty string for driver-selected INBOX or NIL if error
 */

char *mailboxfile (char *dst,char *name)
{
  struct passwd *pw;
  char *s;
  if (!name || !*name || (*name == '{') || (strlen (name) > NETMAXMBX) ||
      ((anonymous || blackBox || restrictBox || (*name == '#')) &&
       (strstr (name,"..") || strstr (name,"//") || strstr (name,"/~"))))
    dst = NIL;			/* invalid name */
  else switch (*name) {		/* determine mailbox type based upon name */
  case '#':			/* namespace name */
				/* #ftp/ namespace */
    if (((name[1] == 'f') || (name[1] == 'F')) &&
	((name[2] == 't') || (name[2] == 'T')) &&
	((name[3] == 'p') || (name[3] == 'P')) &&
	(name[4] == '/') && ftpHome) sprintf (dst,"%s/%s",ftpHome,name+5);
				/* #public/ and #shared/ namespaces */
    else if ((((name[1] == 'p') || (name[1] == 'P')) &&
	      ((name[2] == 'u') || (name[2] == 'U')) &&
	      ((name[3] == 'b') || (name[3] == 'B')) &&
	      ((name[4] == 'l') || (name[4] == 'L')) &&
	      ((name[5] == 'i') || (name[5] == 'I')) &&
	      ((name[6] == 'c') || (name[6] == 'C')) &&
	      (name[7] == '/') && (s = publicHome)) ||
	     (!anonymous && ((name[1] == 's') || (name[1] == 'S')) &&
	      ((name[2] == 'h') || (name[2] == 'H')) &&
	      ((name[3] == 'a') || (name[3] == 'A')) &&
	      ((name[4] == 'r') || (name[4] == 'R')) &&
	      ((name[5] == 'e') || (name[5] == 'E')) &&
	      ((name[6] == 'd') || (name[6] == 'D')) &&
	      (name[7] == '/') && (s = sharedHome)))
      sprintf (dst,"%s/%s",s,compare_cstring (name+8,"INBOX") ?
	       name+8 : "INBOX");
    else dst = NIL;		/* unknown namespace */
    break;

  case '/':			/* root access */
    if (anonymous) dst = NIL;	/* anonymous forbidden to do this */
    else if (blackBox) {	/* other user access if blackbox */
      if (restrictBox & RESTRICTOTHERUSER) dst = NIL;
				/* see if other user INBOX */
      else if ((s = strchr (name+1,'/')) && !compare_cstring (s+1,"INBOX")) {
	*s = '\0';		/* temporarily tie off string */
	sprintf (dst,"%s/%s/INBOX",blackBoxDir,name+1);
	*s = '/';		/* in case caller cares */
      }
      else sprintf (dst,"%s/%s",blackBoxDir,name+1);
    }
    else if ((restrictBox & RESTRICTROOT) && strcmp (name,sysinbox ()))
      dst = NIL;		/* restricted and not access to sysinbox */
    else strcpy (dst,name);	/* unrestricted, copy root name */
    break;
  case '~':			/* other user access */
				/* bad syntax or anonymous can't win */
    if (!*++name || anonymous) dst = NIL;
				/* ~/ equivalent to ordinary name */
    else if (*name == '/') sprintf (dst,"%s/%s",mymailboxdir (),name+1);
				/* other user forbidden if closed/restricted */
    else if (closedBox || (restrictBox & RESTRICTOTHERUSER)) dst = NIL;
    else if (blackBox) {	/* black box form of other user */
				/* see if other user INBOX */
      if ((s = strchr (name,'/')) && compare_cstring (s+1,"INBOX")) {
	*s = '\0';		/* temporarily tie off string */
	sprintf (dst,"%s/%s/INBOX",blackBoxDir,name);
	*s = '/';		/* in case caller cares */
      }
      else sprintf (dst,"%s/%s",blackBoxDir,name);
    }
    else {			/* clear box other user */
				/* copy user name */
      for (s = dst; *name && (*name != '/'); *s++ = *name++);
      *s++ = '\0';		/* tie off user name, look up in passwd file */
      if ((pw = getpwnam (dst)) && pw->pw_dir) {
	if (*name) name++;	/* skip past the slash */
				/* canonicalize case of INBOX */
	if (!compare_cstring (name,"INBOX")) name = "INBOX";
				/* remove trailing / from directory */
	if ((s = strrchr (pw->pw_dir,'/')) && !s[1]) *s = '\0';
				/* don't allow ~root/ if restricted root */
	if ((restrictBox & RESTRICTROOT) && !*pw->pw_dir) dst = NIL;
				/* build final name w/ subdir if needed */
	else if (mailsubdir) sprintf (dst,"%s/%s/%s",pw->pw_dir,mailsubdir,name);
	else sprintf (dst,"%s/%s",pw->pw_dir,name);
      }
      else dst = NIL;		/* no such user */
    }
    break;

  case 'I': case 'i':		/* possible INBOX */
    if (!compare_cstring (name+1,"NBOX")) {
				/* if restricted, use INBOX in mailbox dir */
      if (anonymous || blackBox || closedBox)
	sprintf (dst,"%s/INBOX",mymailboxdir ());
      else *dst = '\0';		/* otherwise driver selects the name */
      break;
    }
				/* drop into to ordinary name case */
  default:			/* ordinary name is easy */
    sprintf (dst,"%s/%s",mymailboxdir (),name);
    break;
  }
  return dst;			/* return final name */
}

/* Dot-lock file locker
 * Accepts: file name to lock
 *	    destination buffer for lock file name
 *	    open file description on file name to lock
 * Returns: T if success, NIL if failure
 */

long dotlock_lock (char *file,DOTLOCK *base,int fd)
{
  int i = locktimeout * 60;
  int j,mask,retry,pi[2],po[2];
  char *s,tmp[MAILTMPLEN];
  struct stat sb;
				/* flush absurd file name */
  if (strlen (file) > 512) return NIL;
				/* build lock filename */
  sprintf (base->lock,"%s.lock",file);
				/* assume no pipe */
  base->pipei = base->pipeo = -1;
  do {				/* make sure not symlink */
    if (!(j = chk_notsymlink (base->lock,&sb))) return NIL;
				/* time out if file older than 5 minutes */
    if ((j > 0) && ((time (0)) >= (sb.st_ctime + locktimeout * 60))) i = 0;
				/* try to create the lock */
    switch (retry = crexcl (base->lock)) {
    case -1:			/* OK to retry */
      if (!(i%15)) {		/* time to notify? */
	sprintf (tmp,"Mailbox %.80s is locked, will override in %d seconds...",
		 file,i);
	MM_LOG (tmp,WARN);
      }
      sleep (1);		/* wait 1 second before next try */
      break;
    case NIL:			/* failure, can't retry */
      i = 0;
      break;
    case T:			/* success, make sure others can break lock */
      chmod (base->lock,(int) dotlock_mode);
      return LONGT;
    }
  } while (i--);		/* until out of retries */
  if (retry < 0) {		/* still returning retry after locktimeout? */
    if (!(j = chk_notsymlink (base->lock,&sb))) return NIL;
    if ((j > 0) && ((time (0)) < (sb.st_ctime + locktimeout * 60))) {
      sprintf (tmp,"Mailbox vulnerable - seizing %ld second old lock",
	       (long) (time (0) - sb.st_ctime));
      MM_LOG (tmp,WARN);
    }
    mask = umask (0);		/* want our lock protection */
    unlink (base->lock);	/* try to remove the old file */
				/* seize the lock */
    if ((i = open (base->lock,O_WRONLY|O_CREAT,(int) dotlock_mode)) >= 0) {
      close (i);		/* don't need descriptor any more */
      sprintf (tmp,"Mailbox %.80s lock overridden",file);
      MM_LOG (tmp,NIL);
      chmod (base->lock,(int) dotlock_mode);
      umask (mask);		/* restore old umask */
      return LONGT;
    }
    umask (mask);		/* restore old umask */
  }

  if (fd >= 0) switch (errno) {
  case EACCES:			/* protection failure? */
    MM_CRITICAL (NIL);		/* go critical */
    if (closedBox || !lockpgm);	/* can't do on closed box or disabled */
    else if ((*lockpgm && stat (lockpgm,&sb)) ||
	     (!*lockpgm && stat (lockpgm = LOCKPGM1,&sb) &&
	      stat (lockpgm = LOCKPGM2,&sb) && stat (lockpgm = LOCKPGM3,&sb)))
      lockpgm = NIL;		/* disable if can't find lockpgm */
    else if (pipe (pi) >= 0) {	/* make command pipes */
      long cf;
      char *argv[4],arg[20];
				/* if input pipes usable create output pipes */
      if ((pi[0] < FD_SETSIZE) && (pi[1] < FD_SETSIZE) && (pipe (po) >= 0)) {
				/* make sure output pipes are usable */
	if ((po[0] >= FD_SETSIZE) || (po[1] >= FD_SETSIZE));
				/* all is good, make inferior process */
	else if (!(j = fork ())) {
	  if (!fork ()) {	/* make grandchild so it's inherited by init */
				/* prepare argument vector */
	    sprintf (arg,"%d",fd);
	    argv[0] = lockpgm; argv[1] = arg;
	    argv[2] = file; argv[3] = NIL;
				/* set parent's I/O to my O/I */
	    dup2 (pi[1],1); dup2 (pi[1],2); dup2 (po[0],0);
				/* close all unnecessary descriptors */
	    for (cf = max (20,max (max (pi[0],pi[1]),max(po[0],po[1])));
		 cf >= 3; --cf) if (cf != fd) close (cf);
				/* be our own process group */
	    setpgrp (0,getpid ());
				/* now run it */
	    _exit (execv (argv[0],argv));
	  }
	  _exit (1);		/* child is done */
	}
	else if (j > 0) {	/* parent process */
	  fd_set rfd;
	  struct timeval tmo;
	  FD_ZERO (&rfd);
	  FD_SET (pi[0],&rfd);
	  tmo.tv_sec = locktimeout * 60;
	  grim_pid_reap (j,NIL);/* reap child; grandchild now owned by init */
				/* read response from locking program */
	  if (select (pi[0]+1,&rfd,0,0,&tmo) &&
	      (read (pi[0],tmp,1) == 1) && (tmp[0] == '+')) {
				/* success, record pipes */
	    base->pipei = pi[0]; base->pipeo = po[1];
				/* close child's side of the pipes */
	    close (pi[1]); close (po[0]);
	    MM_NOCRITICAL (NIL);/* no longer critical */
	    return LONGT;
	  }
	}
	close (po[0]); close (po[1]);
      }
      close (pi[0]); close (pi[1]);
    }

    MM_NOCRITICAL (NIL);	/* no longer critical */
				/* find directory/file delimiter */
    if (s = strrchr (base->lock,'/')) {
      *s = '\0';		/* tie off at directory */
      sprintf(tmp,		/* generate default message */
	      "Mailbox vulnerable - directory %.80s must have 1777 protection",
	      base->lock);
				/* definitely not 1777 if can't stat */
      mask = stat (base->lock,&sb) ? 0 : (sb.st_mode & 1777);
      *s = '/';			/* restore lock name */
      if (mask != 1777) {	/* default warning if not 1777 */
	if (!disableLockWarning) MM_LOG (tmp,WARN);
	break;
      }
    }
  default:
    sprintf (tmp,"Mailbox vulnerable - error creating %.80s: %s",
	     base->lock,strerror (errno));
    if (!disableLockWarning) MM_LOG (tmp,WARN);
    break;
  }
  base->lock[0] = '\0';		/* don't use lock files */
  return NIL;
}

/* Dot-lock file unlocker
 * Accepts: lock file name
 * Returns: T if success, NIL if failure
 */

long dotlock_unlock (DOTLOCK *base)
{
  long ret = LONGT;
  if (base && base->lock[0]) {
    if (base->pipei >= 0) {	/* if running through a pipe unlocker */
      ret = (write (base->pipeo,"+",1) == 1);
				/* nuke the pipes */
      close (base->pipei); close (base->pipeo);
    }
    else ret = !unlink (base->lock);
  }
  return ret;
}

/* Lock file name
 * Accepts: scratch buffer
 *	    file name
 *	    type of locking operation (LOCK_SH or LOCK_EX)
 *	    pointer to return PID of locker
 * Returns: file descriptor of lock or negative if error
 */

int lockname (char *lock,char *fname,int op,long *pid)
{
  struct stat sbuf;
  *pid = 0;			/* no locker PID */
  return stat (fname,&sbuf) ? -1 : lock_work (lock,&sbuf,op,pid);
}


/* Lock file descriptor
 * Accepts: file descriptor
 *	    lock file name buffer
 *	    type of locking operation (LOCK_SH or LOCK_EX)
 * Returns: file descriptor of lock or negative if error
 */

int lockfd (int fd,char *lock,int op)
{
  struct stat sbuf;
  return fstat (fd,&sbuf) ? -1 : lock_work (lock,&sbuf,op,NIL);
}

/* Lock file name worker
 * Accepts: lock file name
 *	    pointer to stat() buffer
 *	    type of locking operation (LOCK_SH or LOCK_EX)
 *	    pointer to return PID of locker
 * Returns: file descriptor of lock or negative if error
 */

int lock_work (char *lock,void *sb,int op,long *pid)
{
  struct stat lsb,fsb;
  struct stat *sbuf = (struct stat *) sb;
  char tmp[MAILTMPLEN];
  long i;
  int fd;
  int mask = umask (0);
  if (pid) *pid = 0;		/* initialize return PID */
				/* make temporary lock file name */
  sprintf (lock,"%s/.%lx.%lx",closedBox ? "" : tmpdir,
	   (unsigned long) sbuf->st_dev,(unsigned long) sbuf->st_ino);
  while (T) {			/* until get a good lock */
    do switch ((int) chk_notsymlink (lock,&lsb)) {
    case 1:			/* exists just once */
      if (((fd = open (lock,O_RDWR,shlock_mode)) >= 0) ||
	  (errno != ENOENT) || (chk_notsymlink (lock,&lsb) >= 0)) break;
    case -1:			/* name doesn't exist */
      fd = open (lock,O_RDWR|O_CREAT|O_EXCL,shlock_mode);
      break;
    default:			/* multiple hard links */
      MM_LOG ("hard link to lock name",ERROR);
      syslog (LOG_CRIT,"SECURITY PROBLEM: hard link to lock name: %.80s",lock);
    case 0:			/* symlink (already did syslog) */
      umask (mask);		/* restore old mask */
      return -1;		/* fail: no lock file */
    } while ((fd < 0) && (errno == EEXIST));
    if (fd < 0) {		/* failed to get file descriptor */
      syslog (LOG_INFO,"Mailbox lock file %s open failure: %s",lock,
	      strerror (errno));
      if (!closedBox) {		/* more explicit snarl for bad configuration */
	if (stat (tmpdir,&lsb))
	  syslog (LOG_CRIT,"SYSTEM ERROR: no %s: %s",tmpdir,strerror (errno));
	else if ((lsb.st_mode & 01777) != 01777) {
	  sprintf (tmp,"Can't lock for write: %.80s must have 1777 protection",
		   tmpdir);
	  MM_LOG (tmp,WARN);
	}
      }
      umask (mask);		/* restore old mask */
      return -1;		/* fail: can't open lock file */
    }

				/* non-blocking form */
    if (op & LOCK_NB) i = flock (fd,op);
    else {			/* blocking form */
      (*mailblocknotify) (BLOCK_FILELOCK,NIL);
      i = flock (fd,op);
      (*mailblocknotify) (BLOCK_NONE,NIL);
    }
    if (i) {			/* failed, get other process' PID */
      if (pid && !fstat (fd,&fsb) && (i = min (fsb.st_size,MAILTMPLEN-1)) &&
	  (read (fd,tmp,i) == i) && !(tmp[i] = 0) && ((i = atol (tmp)) > 0))
	*pid = i;
      close (fd);		/* failed, give up on lock */
      umask (mask);		/* restore old mask */
      return -1;		/* fail: can't lock */
    }
				/* make sure this lock is good for us */
    if (!lstat (lock,&lsb) && ((lsb.st_mode & S_IFMT) != S_IFLNK) &&
	!fstat (fd,&fsb) && (lsb.st_dev == fsb.st_dev) &&
	(lsb.st_ino == fsb.st_ino) && (fsb.st_nlink == 1)) break;
    close (fd);			/* lock not right, drop fd and try again */
  }
  chmod (lock,shlock_mode);	/* make sure mode OK (don't use fchmod()) */
  umask (mask);			/* restore old mask */
  return fd;			/* success */
}

/* Check to make sure not a symlink
 * Accepts: file name
 *	    stat buffer
 * Returns: -1 if doesn't exist, NIL if symlink, else number of hard links
 */

long chk_notsymlink (char *name,void *sb)
{
  struct stat *sbuf = (struct stat *) sb;
				/* name exists? */
  if (lstat (name,sbuf)) return -1;
				/* forbid symbolic link */
  if ((sbuf->st_mode & S_IFMT) == S_IFLNK) {
    MM_LOG ("symbolic link on lock name",ERROR);
    syslog (LOG_CRIT,"SECURITY PROBLEM: symbolic link on lock name: %.80s",
	    name);
    return NIL;
  }
  return (long) sbuf->st_nlink;	/* return number of hard links */
}


/* Unlock file descriptor
 * Accepts: file descriptor
 *	    lock file name from lockfd()
 */

void unlockfd (int fd,char *lock)
{
				/* delete the file if no sharers */
  if (!flock (fd,LOCK_EX|LOCK_NB)) unlink (lock);
  flock (fd,LOCK_UN);		/* unlock it */
  close (fd);			/* close it */
}

/* Set proper file protection for mailbox
 * Accepts: mailbox name
 *	    actual file path name
 * Returns: T, always
 */

long set_mbx_protections (char *mailbox,char *path)
{
  struct stat sbuf;
  int mode = (int) mbx_protection;
  if (*mailbox == '#') {	/* possible namespace? */
      if (((mailbox[1] == 'f') || (mailbox[1] == 'F')) &&
	  ((mailbox[2] == 't') || (mailbox[2] == 'T')) &&
	  ((mailbox[3] == 'p') || (mailbox[3] == 'P')) &&
	  (mailbox[4] == '/')) mode = (int) ftp_protection;
      else if (((mailbox[1] == 'p') || (mailbox[1] == 'P')) &&
	       ((mailbox[2] == 'u') || (mailbox[2] == 'U')) &&
	       ((mailbox[3] == 'b') || (mailbox[3] == 'B')) &&
	       ((mailbox[4] == 'l') || (mailbox[4] == 'L')) &&
	       ((mailbox[5] == 'i') || (mailbox[5] == 'I')) &&
	       ((mailbox[6] == 'c') || (mailbox[6] == 'C')) &&
	       (mailbox[7] == '/')) mode = (int) public_protection;
      else if (((mailbox[1] == 's') || (mailbox[1] == 'S')) &&
	       ((mailbox[2] == 'h') || (mailbox[2] == 'H')) &&
	       ((mailbox[3] == 'a') || (mailbox[3] == 'A')) &&
	       ((mailbox[4] == 'r') || (mailbox[4] == 'R')) &&
	       ((mailbox[5] == 'e') || (mailbox[5] == 'E')) &&
	       ((mailbox[6] == 'd') || (mailbox[6] == 'D')) &&
	       (mailbox[7] == '/')) mode = (int) shared_protection;
  }
				/* if a directory */
  if (!stat (path,&sbuf) && ((sbuf.st_mode & S_IFMT) == S_IFDIR)) {
				/* set owner search if allow read or write */
    if (mode & 0600) mode |= 0100;
    if (mode & 060) mode |= 010;/* set group search if allow read or write */
    if (mode & 06) mode |= 01;	/* set world search if allow read or write */
				/* preserve directory SGID bit */
    if (sbuf.st_mode & S_ISGID) mode |= S_ISGID;
  }
  chmod (path,mode);		/* set the new protection, ignore failure */
  return LONGT;
}

/* Get proper directory protection
 * Accepts: mailbox name
 * Returns: directory mode, always
 */

long get_dir_protection (char *mailbox)
{
  if (*mailbox == '#') {	/* possible namespace? */
      if (((mailbox[1] == 'f') || (mailbox[1] == 'F')) &&
	  ((mailbox[2] == 't') || (mailbox[2] == 'T')) &&
	  ((mailbox[3] == 'p') || (mailbox[3] == 'P')) &&
	  (mailbox[4] == '/')) return ftp_dir_protection;
      else if (((mailbox[1] == 'p') || (mailbox[1] == 'P')) &&
	       ((mailbox[2] == 'u') || (mailbox[2] == 'U')) &&
	       ((mailbox[3] == 'b') || (mailbox[3] == 'B')) &&
	       ((mailbox[4] == 'l') || (mailbox[4] == 'L')) &&
	       ((mailbox[5] == 'i') || (mailbox[5] == 'I')) &&
	       ((mailbox[6] == 'c') || (mailbox[6] == 'C')) &&
	       (mailbox[7] == '/')) return public_dir_protection;
      else if (((mailbox[1] == 's') || (mailbox[1] == 'S')) &&
	       ((mailbox[2] == 'h') || (mailbox[2] == 'H')) &&
	       ((mailbox[3] == 'a') || (mailbox[3] == 'A')) &&
	       ((mailbox[4] == 'r') || (mailbox[4] == 'R')) &&
	       ((mailbox[5] == 'e') || (mailbox[5] == 'E')) &&
	       ((mailbox[6] == 'd') || (mailbox[6] == 'D')) &&
	       (mailbox[7] == '/')) return shared_dir_protection;
  }
  return dir_protection;
}

/* Determine default prototype stream to user
 * Accepts: type (NIL for create, T for append)
 * Returns: default prototype stream
 */

MAILSTREAM *default_proto (long type)
{
  myusername ();		/* make sure initialized */
				/* return default driver's prototype */
  return type ? appendProto : createProto;
}


/* Set up user flags for stream
 * Accepts: MAIL stream
 * Returns: MAIL stream with user flags set up
 */

MAILSTREAM *user_flags (MAILSTREAM *stream)
{
  int i;
  myusername ();		/* make sure initialized */
  for (i = 0; i < NUSERFLAGS && userFlags[i]; ++i)
    if (!stream->user_flags[i]) stream->user_flags[i] = cpystr (userFlags[i]);
  return stream;
}


/* Return nth user flag
 * Accepts: user flag number
 * Returns: flag
 */

char *default_user_flag (unsigned long i)
{
  myusername ();		/* make sure initialized */
  return userFlags[i];
}

/* Process rc file
 * Accepts: file name
 *	    .mminit flag
 * Don't use this feature.
 */

void dorc (char *file,long flag)
{
  int i;
  char *s,*t,*k,*r,tmp[MAILTMPLEN],tmpx[MAILTMPLEN];
  extern MAILSTREAM CREATEPROTO;
  extern MAILSTREAM EMPTYPROTO;
  DRIVER *d;
  FILE *f;
  if ((f = fopen (file ? file : SYSCONFIG,"r")) &&
      (s = fgets (tmp,MAILTMPLEN,f)) && (t = strchr (s,'\n'))) do {
    *t++ = '\0';		/* tie off line, find second space */
    if ((k = strchr (s,' ')) && (k = strchr (++k,' '))) {
      *k++ = '\0';		/* tie off two words */
      if (!compare_cstring (s,"set keywords") && !userFlags[0]) {
				/* yes, get first keyword */
	k = strtok_r (k,", ",&r);
				/* copy keyword list */
	for (i = 0; k && i < NUSERFLAGS; ++i) if (strlen (k) <= MAXUSERFLAG) {
	  if (userFlags[i]) fs_give ((void **) &userFlags[i]);
	  userFlags[i] = cpystr (k);
	  k = strtok_r (NIL,", ",&r);
	}
	if (flag) break;	/* found "set keywords" in .mminit */
      }

      else if (!flag) {		/* none of these valid in .mminit */
	if (myUserName) {	/* only valid if logged in */
	  if (!compare_cstring (s,"set new-mailbox-format") ||
	      !compare_cstring (s,"set new-folder-format")) {
	    if (!compare_cstring (k,"same-as-inbox")) {
	      if (d = mail_valid (NIL,"INBOX",NIL)) {
		if (!compare_cstring (d->name,"mbox"))
		  d = (DRIVER *) mail_parameters (NIL,GET_DRIVER,
						  (void *) "unix");
		else if (!compare_cstring (d->name,"dummy")) d = NIL;
	      }
	      createProto = d ? ((*d->open) (NIL)) : &CREATEPROTO;
	    }
	    else if (!compare_cstring (k,"system-standard"))
	      createProto = &CREATEPROTO;
	    else {		/* canonicalize mbox to unix */
	      if (!compare_cstring (k,"mbox")) k = "unix";
				/* see if a driver name */
	      if (d = (DRIVER *) mail_parameters (NIL,GET_DRIVER,(void *) k))
		createProto = (*d->open) (NIL);
	      else {		/* duh... */
		sprintf (tmpx,"Unknown new mailbox format in %s: %s",
			 file ? file : SYSCONFIG,k);
		MM_LOG (tmpx,WARN);
	      }
	    }
	  }
	  if (!compare_cstring (s,"set empty-mailbox-format") ||
	      !compare_cstring (s,"set empty-folder-format")) {
	    if (!compare_cstring (k,"invalid")) appendProto = NIL;
	    else if (!compare_cstring (k,"same-as-inbox"))
	      appendProto = ((d = mail_valid (NIL,"INBOX",NIL)) &&
			     compare_cstring (d->name,"dummy")) ?
			       ((*d->open) (NIL)) : &EMPTYPROTO;
	    else if (!compare_cstring (k,"system-standard"))
	      appendProto = &EMPTYPROTO;
	    else {		/* see if a driver name */
	      for (d = (DRIVER *) mail_parameters (NIL,GET_DRIVERS,NIL);
		   d && compare_cstring (d->name,k); d = d->next);
	      if (d) appendProto = (*d->open) (NIL);
	      else {		/* duh... */
		sprintf (tmpx,"Unknown empty mailbox format in %s: %s",
			 file ? file : SYSCONFIG,k);
		MM_LOG (tmpx,WARN);
	      }
	    }
	  }
	}

	if (!compare_cstring (s,"set local-host")) {
	  fs_give ((void **) &myLocalHost);
	  myLocalHost = cpystr (k);
	}
	else if (!compare_cstring (s,"set news-active-file")) {
	  fs_give ((void **) &newsActive);
	  newsActive = cpystr (k);
	}
	else if (!compare_cstring (s,"set news-spool-directory")) {
	  fs_give ((void **) &newsSpool);
	  newsSpool = cpystr (k);
	}
	else if (!compare_cstring (s,"set mh-path"))
	  mail_parameters (NIL,SET_MHPATH,(void *) k);
	else if (!compare_cstring (s,"set mh-allow-inbox"))
	  mail_parameters (NIL,SET_MHALLOWINBOX,(void *) atol (k));
	else if (!compare_cstring (s,"set news-state-file")) {
	  fs_give ((void **) &myNewsrc);
	  myNewsrc = cpystr (k);
	}
	else if (!compare_cstring (s,"set ftp-export-directory")) {
	  fs_give ((void **) &ftpHome);
	  ftpHome = cpystr (k);
	}
	else if (!compare_cstring (s,"set public-home-directory")) {
	  fs_give ((void **) &publicHome);
	  publicHome = cpystr (k);
	}
	else if (!compare_cstring (s,"set shared-home-directory")) {
	  fs_give ((void **) &sharedHome);
	  sharedHome = cpystr (k);
	}
	else if (!compare_cstring (s,"set system-inbox")) {
	  fs_give ((void **) &sysInbox);
	  sysInbox = cpystr (k);
	}
	else if (!compare_cstring (s,"set mail-subdirectory")) {
	  fs_give ((void **) &mailsubdir);
	  mailsubdir = cpystr (k);
	}
	else if (!compare_cstring (s,"set from-widget"))
	  mail_parameters (NIL,SET_FROMWIDGET,
			   compare_cstring (k,"header-only") ?
			   VOIDT : NIL);

	else if (!compare_cstring (s,"set rsh-command"))
	  mail_parameters (NIL,SET_RSHCOMMAND,(void *) k);
	else if (!compare_cstring (s,"set rsh-path"))
	  mail_parameters (NIL,SET_RSHPATH,(void *) k);
	else if (!compare_cstring (s,"set ssh-command"))
	  mail_parameters (NIL,SET_SSHCOMMAND,(void *) k);
	else if (!compare_cstring (s,"set ssh-path"))
	  mail_parameters (NIL,SET_SSHPATH,(void *) k);
	else if (!compare_cstring (s,"set tcp-open-timeout"))
	  mail_parameters (NIL,SET_OPENTIMEOUT,(void *) atol (k));
	else if (!compare_cstring (s,"set tcp-read-timeout"))
	  mail_parameters (NIL,SET_READTIMEOUT,(void *) atol (k));
	else if (!compare_cstring (s,"set tcp-write-timeout"))
	  mail_parameters (NIL,SET_WRITETIMEOUT,(void *) atol (k));
	else if (!compare_cstring (s,"set rsh-timeout"))
	  mail_parameters (NIL,SET_RSHTIMEOUT,(void *) atol (k));
	else if (!compare_cstring (s,"set ssh-timeout"))
	  mail_parameters (NIL,SET_SSHTIMEOUT,(void *) atol (k));
	else if (!compare_cstring (s,"set maximum-login-trials"))
	  mail_parameters (NIL,SET_MAXLOGINTRIALS,(void *) atol (k));
	else if (!compare_cstring (s,"set lookahead"))
	  mail_parameters (NIL,SET_LOOKAHEAD,(void *) atol (k));
	else if (!compare_cstring (s,"set prefetch"))
	  mail_parameters (NIL,SET_PREFETCH,(void *) atol (k));
	else if (!compare_cstring (s,"set close-on-error"))
	  mail_parameters (NIL,SET_CLOSEONERROR,(void *) atol (k));
	else if (!compare_cstring (s,"set imap-port"))
	  mail_parameters (NIL,SET_IMAPPORT,(void *) atol (k));
	else if (!compare_cstring (s,"set pop3-port"))
	  mail_parameters (NIL,SET_POP3PORT,(void *) atol (k));
	else if (!compare_cstring (s,"set uid-lookahead"))
	  mail_parameters (NIL,SET_UIDLOOKAHEAD,(void *) atol (k));
	else if (!compare_cstring (s,"set try-ssl-first"))
	  mail_parameters (NIL,SET_TRYSSLFIRST,(void *) atol (k));

	else if (!compare_cstring (s,"set mailbox-protection"))
	  mbx_protection = atol (k);
	else if (!compare_cstring (s,"set directory-protection"))
	  dir_protection = atol (k);
	else if (!compare_cstring (s,"set lock-protection"))
	  dotlock_mode = atol (k);
	else if (!compare_cstring (s,"set ftp-protection"))
	  ftp_protection = atol (k);
	else if (!compare_cstring (s,"set public-protection"))
	  public_protection = atol (k);
	else if (!compare_cstring (s,"set shared-protection"))
	  shared_protection = atol (k);
	else if (!compare_cstring (s,"set ftp-directory-protection"))
	  ftp_dir_protection = atol (k);
	else if (!compare_cstring (s,"set public-directory-protection"))
	  public_dir_protection = atol (k);
	else if (!compare_cstring (s,"set shared-directory-protection"))
	  shared_dir_protection = atol (k);
	else if (!compare_cstring (s,"set dot-lock-file-timeout"))
	  locktimeout = atoi (k);
	else if (!compare_cstring (s,"set disable-fcntl-locking"))
	  fcntlhangbug = atoi (k);
	else if (!compare_cstring (s,"set disable-lock-warning"))
	  disableLockWarning = atoi (k);
	else if (!compare_cstring (s,"set disable-unix-UIDs-and-keywords"))
	  has_no_life = atoi (k);
	else if (!compare_cstring (s,"set hide-dot-files"))
	  hideDotFiles = atoi (k);
	else if (!compare_cstring (s,"set list-maximum-level"))
	  list_max_level = atol (k);
	else if (!compare_cstring (s,"set trust-dns"))
	  mail_parameters (NIL,SET_TRUSTDNS,(void *) atol (k));
	else if (!compare_cstring (s,"set sasl-uses-ptr-name"))
	  mail_parameters (NIL,SET_SASLUSESPTRNAME,(void *) atol (k));
	else if (!compare_cstring (s,"set network-filesystem-stat-bug"))
	  netfsstatbug = atoi (k);
	else if (!compare_cstring (s,"set nntp-range"))
	  mail_parameters (NIL,SET_NNTPRANGE,(void *) atol (k));

	else if (!file) {	/* only allowed in system init */
	  if (!compare_cstring (s,"set black-box-directory") &&
	      !blackBoxDir) blackBoxDir = cpystr (k);
	  else if (!compare_cstring(s,"set black-box-default-home-directory")&&
		   blackBoxDir && !blackBoxDefaultHome)
	    blackBoxDefaultHome = cpystr (k);
	  else if (!compare_cstring (s,"set anonymous-home-directory") &&
		   !anonymousHome) anonymousHome = cpystr (k);
				/* It's tempting to allow setting the CA path
				 * in a user init.  However, that opens up a
				 * vector of attack big enough to drive a
				 * truck through...  Resist the temptation.
				 */
	  else if (!compare_cstring (s,"set CA-certificate-path"))
	    sslCApath = cpystr (k);
	  else if (!compare_cstring (s,"set disable-plaintext"))
	    disablePlaintext = atoi (k);
	  else if (!compare_cstring (s,"set allowed-login-attempts"))
	    logtry = atoi (k);
	  else if (!compare_cstring (s,"set chroot-server"))
	    closedBox = atoi (k);
	  else if (!compare_cstring (s,"set restrict-mailbox-access"))
	    for (k = strtok_r (k,", ",&r); k; k = strtok_r (NIL,", ",&r)) {
	      if (!compare_cstring (k,"root")) restrictBox |= RESTRICTROOT;
	      else if (!compare_cstring (k,"otherusers"))
		restrictBox |= RESTRICTOTHERUSER;
	      else if (!compare_cstring (k,"all")) restrictBox = -1;
	    }
	  else if (!compare_cstring (s,"set advertise-the-world"))
	    advertisetheworld = atoi (k);
	  else if (!compare_cstring (s,"set limited-advertise"))
	    limitedadvertise = atoi (k);
	  else if (!compare_cstring
		   (s,"set disable-automatic-shared-namespaces"))
	    noautomaticsharedns = atoi (k);
	  else if (!compare_cstring (s,"set allow-user-config"))
	    allowuserconfig = atoi (k);
	  else if (!compare_cstring (s,"set allow-reverse-dns"))
	    mail_parameters (NIL,SET_ALLOWREVERSEDNS,(void *) atol (k));
	  else if (!compare_cstring (s,"set k5-cp-uses-service-name"))
	    kerb_cp_svr_name = atoi (k);
				/* must appear in file after any
				 * "set disable-plaintext" command! */
	  else if (!compare_cstring (s,"set plaintext-allowed-clients")) {
	    for (k = strtok_r (k,", ",&r); k && !tcp_isclienthost (k);
		 k = strtok_r (NIL,", ",&r));
	    if (k) disablePlaintext = 0;
	  }
	}
      }
    }
  } while ((s = fgets (tmp,MAILTMPLEN,f)) && (t = strchr (s,'\n')));
  if (f) fclose (f);		/* flush the file */
}

/* INBOX create function for tmail/dmail use only
 * Accepts: mail stream
 *	    path name buffer, preloaded with driver-dependent path
 * Returns: T on success, NIL on failure
 *
 * This routine is evil and a truly incredible kludge.  It is private for
 * tmail/dmail and is not supported for any other application.
 */

long path_create (MAILSTREAM *stream,char *path)
{
  long ret;
  short rsave = restrictBox;
  restrictBox = NIL;		/* can't restrict */
  if (blackBox) {		/* if black box */
				/* toss out driver dependent names */
    sprintf (path,"%s/INBOX",mymailboxdir ());
    blackBox = NIL;		/* well that's evil - evil is going on */
    ret = mail_create (stream,path);
    blackBox = T;		/* restore the box */
  }
				/* easy thing otherwise */
  else ret = mail_create (stream,path);
  restrictBox = rsave;		/* restore restrictions */
  return ret;
}

/* Default block notify routine
 * Accepts: reason for calling
 *	    data
 * Returns: data
 */

void *mm_blocknotify (int reason,void *data)
{
  void *ret = data;
  switch (reason) {
  case BLOCK_SENSITIVE:		/* entering sensitive code */
    ret = (void *) (unsigned long) alarm (0);
    break;
  case BLOCK_NONSENSITIVE:	/* exiting sensitive code */
    if ((unsigned long) data) alarm ((unsigned long) data);
    break;
  default:			/* ignore all other reasons */
    break;
  }
  return ret;
}

Youez - 2016 - github.com/yon3zu
LinuXploit