home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume34 / mserv / part05 < prev    next >
Text File  |  1993-01-06  |  61KB  |  2,200 lines

  1. Newsgroups: comp.sources.misc
  2. From: jv@squirrel.mh.nl (Johan Vromans)
  3. Subject: v34i096:  mserv - Squirrel Mail Server Software, version 3.1, Part05/06
  4. Message-ID: <1993Jan7.034945.11784@sparky.imd.sterling.com>
  5. X-Md4-Signature: 26a833bf806dff65e06394688d5226f6
  6. Date: Thu, 7 Jan 1993 03:49:45 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jv@squirrel.mh.nl (Johan Vromans)
  10. Posting-number: Volume 34, Issue 96
  11. Archive-name: mserv/part05
  12. Environment: Perl
  13. Supersedes: mserv-3.0: Volume 30, Issue 46-49
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # Contents:  mserv-3.1/Makefile mserv-3.1/chat2.pl
  20. #   mserv-3.1/do_report.pl mserv-3.1/dr_mail.pl mserv-3.1/mlistener.pl
  21. #   mserv-3.1/pr_ftp.pl mserv-3.1/pr_help.pl mserv-3.1/report.pl
  22. #   mserv-3.1/ud_sample1.pl
  23. # Wrapped by kent@sparky on Wed Jan  6 21:39:49 1993
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 5 (of 6)."'
  27. if test -f 'mserv-3.1/Makefile' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'mserv-3.1/Makefile'\"
  29. else
  30.   echo shar: Extracting \"'mserv-3.1/Makefile'\" \(5083 characters\)
  31.   sed "s/^X//" >'mserv-3.1/Makefile' <<'END_OF_FILE'
  32. X# Makefile -- for mail server
  33. X# SCCS Status     : %Z%@ %M%    %I%
  34. X# Author          : Johan Vromans
  35. X# Created On      : Fri May  1 15:44:47 1992
  36. X# Last Modified By: Johan Vromans
  37. X# Last Modified On: Wed Dec 23 23:13:14 1992
  38. X# Update Count    : 109
  39. X# Status          : 
  40. X
  41. XSHELL    = /bin/sh
  42. XCC    = gcc -Wall
  43. XCFLAGS    = -O
  44. X
  45. X# Perl 4.035 needs fixes!
  46. XPERL    = /usr/local/bin/perl
  47. X# Where programs and files reside.
  48. XLIBDIR    = /usr/local/lib/mserv
  49. X# Where help data will be installed.
  50. XPUBDIR    = $(LIBDIR)/pub
  51. X# The owner of the mail server files
  52. XSERVER    = mserv
  53. X
  54. X# Perl scripts that will be public executable.
  55. XPEARLS    = process dorequest unpack makeindex chkconfig report do_report
  56. X# Misc. files.
  57. XFILES    = rfc822.pl ms_common.pl patchlevel.h \
  58. X    ms_lock.pl ftp.pl chat2.pl dateconv.pl \
  59. X    dr_mail.pl dr_uucp.pl dr_pack.pl \
  60. X    pr_isearch.pl pr_dsearch.pl pr_doindex.pl pr_dowork.pl \
  61. X    pr_parse.pl pr_ftp.pl pr_help.pl
  62. X# Config data. Will not replace existing files.
  63. XCONFIG    = ms_config.pl mserv.hints mserv.notes mserv.notesi
  64. X# Public executable shell scripts.
  65. XSHELLS    = do_runq
  66. X# These files will be created, if needed
  67. XTOUCH    = logfile lockfile queue .errrun
  68. X# Public services.
  69. XAIDS    = HELP unpack.pl
  70. X
  71. Xall:    $(PEARLS) mlistener
  72. X    @echo "Use \"make listener\" to generate the listener program"
  73. X    @echo "Use \"make ixlookup\" if you selected index lookup"
  74. X
  75. X$(PEARLS) mlistener:
  76. X    @for prog in $(PEARLS) mlistener; do \
  77. X        echo "Preparing $$prog..."; \
  78. X        rm -f $$prog; \
  79. X        sed -e '1s|/usr/local/bin/perl|$(PERL)|' \
  80. X            -e 's|/usr/local/lib/mserv|$(LIBDIR)|' \
  81. X            $$prog.pl >$$prog; \
  82. X    done
  83. X
  84. Xinstall: $(PEARLS)
  85. X    -mkdir $(LIBDIR)
  86. X    @for prog in $(PEARLS); do \
  87. X        echo "Installing $$prog..."; \
  88. X        install -c -m 0555 $$prog $(LIBDIR)/$$prog; \
  89. X    done
  90. X    @for prog in $(SHELLS); do \
  91. X        echo "Installing $$prog..."; \
  92. X        install -c -m 0555 $$prog.sh $(LIBDIR)/$$prog; \
  93. X    done
  94. X    @for prog in $(FILES); do \
  95. X        echo "Installing $$prog..."; \
  96. X        install -c -m 0444 $$prog $(LIBDIR); \
  97. X    done
  98. X    @for prog in $(TOUCH); do \
  99. X        if [ -f $(LIBDIR)/$$prog ]; then \
  100. X        true; \
  101. X        else \
  102. X        echo "Creating $$prog..."; \
  103. X        cat < /dev/null > $(LIBDIR)/$$prog; \
  104. X        fi; \
  105. X    done
  106. X    @for prog in $(CONFIG); do \
  107. X        if [ -f $(LIBDIR)/$$prog ]; then \
  108. X        echo "Installing $$prog as NEW-$$prog..."; \
  109. X        echo "IMPORTANT: Update $$prog by hand if needed!"; \
  110. X        install -c -m 0644 $$prog $(LIBDIR)/NEW-$$prog; \
  111. X        else \
  112. X        echo "Installing $$prog..."; \
  113. X        install -c -m 0644 $$prog $(LIBDIR); \
  114. X        fi \
  115. X    done
  116. X    -mkdir $(PUBDIR)
  117. X    @for prog in $(AIDS); do \
  118. X        echo "Installing $$prog in $(PUBDIR)..."; \
  119. X        install -c -m 0444 $$prog $(PUBDIR)/$$prog; \
  120. X    done
  121. X    -(cd $(PUBDIR); rm -f help; ln HELP help)
  122. X    @echo "Use \"make install-listener\" to install the listener program"
  123. X    @echo "Use \"make install-ixlookup\" to install the ixlookup program"
  124. X
  125. X################ Listener ################
  126. X
  127. Xlistener: mlistener
  128. X    rm -f listener listener.c
  129. X    $(PERL) mlistener -verbose > listener.c
  130. X    $(CC) $(CFLAGS) -o listener listener.c
  131. X
  132. X# Install setuid to the installer...
  133. Xinstall-listener:    listener
  134. X    rm -f $(LIBDIR)/listener
  135. X    install -s -c listener $(LIBDIR)/listener
  136. X    chmod -w,+x,u+s $(LIBDIR)/listener
  137. X
  138. X################ ixlookup ################
  139. X
  140. X# ixlookup is based on GNU find/locate.
  141. X# If you have GNU find 3.6 or later, you can use the locate program.
  142. X# For locate 3.5, a patch is available to create a customized version
  143. X# of this program. "make ixlookup" will build it.
  144. X# Set GNUFIND to indicate where the source of GNU locate, includes
  145. X# and find lib can be found.
  146. X# Reference version is GNU find 3.5.
  147. XGNUFIND = /beethoven/arch/GNU/find-3.5
  148. X
  149. Xixlookup.c: $(GNUFIND)/locate/locate.c ixlookup.patch
  150. X    rm -f ixlookup.c
  151. X    cp  $(GNUFIND)/locate/locate.c ixlookup.c
  152. X    patch -p0 -N < ixlookup.patch
  153. X
  154. Xixlookup:    ixlookup.c
  155. X    rm -f ixlookup
  156. X    $(CC) $(CFLAGS) '-DFCODES="$(LIBDIR)/find.codes"' \
  157. X        -I$(GNUFIND)/lib -o ixlookup ixlookup.c \
  158. X        $(GNUFIND)/lib/libfind.a
  159. X
  160. Xinstall-ixlookup:    ixlookup
  161. X    install -s -m 0555 -c ixlookup $(LIBDIR)
  162. X
  163. X################ Cleanup ################
  164. X
  165. Xclean:
  166. X    rm -f *~ core a.out $(PEARLS) mlistener listener listener.c \
  167. X        *.orig *.rej ixlookup.c ixlookup
  168. X
  169. X################ Maintenance ################
  170. X
  171. XREV    = X3.01
  172. X
  173. Xdist:    tar.Z
  174. X
  175. Xtar.Z:    HELP INSTALL
  176. X    rm -f mserv-$(REV)
  177. X    ln -s . mserv-$(REV)
  178. X    sed < MANIFEST -e "s/^/mserv-$(REV)\//" | \
  179. X        pdtar -zcv -T - -f mserv-$(REV).tar.Z
  180. X    rm -f mserv-$(REV)
  181. X
  182. Xshar:    HELP INSTALL
  183. X    rm -f mserv-$(REV)
  184. X    ln -s . mserv-$(REV)
  185. X    rm -f mserv-$(REV).shar.*
  186. X    sed < MANIFEST -e "s/^/mserv-$(REV)\//" | \
  187. X        shar -p -F -S -L 50 -o mserv-$(REV).shar \
  188. X        -a -n mserv-$(REV).shar -s 'jv@mh.nl (Johan Vromans)'
  189. X    rm -f mserv-$(REV)
  190. X    ls -l mserv-$(REV).shar.*
  191. X
  192. XAUX   = Makefile ms_config.pl ChangeLog* Misc
  193. X
  194. XTZ:
  195. X    tar cvf - $(AUX) SCCS | compress > mserv.TZ
  196. X
  197. X#
  198. X# Create formatted documents (Ascii or PostScript)
  199. X#
  200. X.SUFFIXES:    .ps .txt .asc
  201. XMH_DOC    = mh_doc -language uk
  202. X
  203. X.txt.ps:
  204. X    rm -f $@
  205. X    $(MH_DOC) -expert -verbose -ps -printer foo:ps -output $@ $<
  206. X
  207. X.txt.asc:
  208. X    rm -f $@
  209. X    $(MH_DOC) -text -output $@ $<
  210. X
  211. XHELP:    usrguide.asc
  212. X    rm -f $@ && cp $< $@ && chmod -w $@
  213. X
  214. XINSTALL:    mservmgr.asc
  215. X    rm -f $@ && cp $< $@ && chmod -w $@
  216. END_OF_FILE
  217.   if test 5083 -ne `wc -c <'mserv-3.1/Makefile'`; then
  218.     echo shar: \"'mserv-3.1/Makefile'\" unpacked with wrong size!
  219.   fi
  220.   # end of 'mserv-3.1/Makefile'
  221. fi
  222. if test -f 'mserv-3.1/chat2.pl' -a "${1}" != "-c" ; then 
  223.   echo shar: Will not clobber existing file \"'mserv-3.1/chat2.pl'\"
  224. else
  225.   echo shar: Extracting \"'mserv-3.1/chat2.pl'\" \(8328 characters\)
  226.   sed "s/^X//" >'mserv-3.1/chat2.pl' <<'END_OF_FILE'
  227. X# chat2.pl -- 
  228. X# SCCS Status     : @(#)@ chat2    1.1
  229. X# Last Modified By: Johan Vromans
  230. X# Last Modified On: Fri Dec  4 00:12:05 1992
  231. X# Update Count    : 3
  232. X# Status          : OK
  233. X
  234. X## chat.pl: chat with a server
  235. X## V2.01.alpha.3 91/04/30
  236. X## Randal L. Schwartz <merlyn@iwarp.intel.com>
  237. X## minor change by A.Macpherson@bnr.co.uk
  238. X# Adopted (w/o changes) for use by the Squirrel Mail Server Software 
  239. X# by Johan Vromans <jv@mh.nl>.
  240. X
  241. Xpackage chat;
  242. X
  243. X$sockaddr = 'S n a4 x8';
  244. Xchop($thishost = `hostname`);
  245. X# We may be multi-homed, start with 0, fixup once connexion is made
  246. X$thisaddr = "\0\0\0\0" ;
  247. X$thisproc = pack($sockaddr, 2, 0, $thisaddr);
  248. X
  249. X# *S = symbol for current I/O, gets assigned *chatsymbol....
  250. X$next = "chatsymbol000000"; # next one
  251. X$nextpat = "^chatsymbol"; # patterns that match next++, ++, ++, ++
  252. X
  253. X
  254. X## $handle = &chat'open_port("server.address",$port_number);
  255. X## opens a named or numbered TCP server
  256. X
  257. Xsub open_port { ## public
  258. X    local($server, $port) = @_;
  259. X
  260. X    local($serveraddr,$serverproc);
  261. X    $thisaddr = "\0\0\0\0" ;
  262. X    $thisproc = pack($sockaddr, 2, 0, $thisaddr);
  263. X
  264. X    *S = ++$next;
  265. X    if ($server =~ /^(\d+)+\.(\d+)\.(\d+)\.(\d+)$/) {
  266. X        $serveraddr = pack('C4', $1, $2, $3, $4);
  267. X    } else {
  268. X        local(@x) = gethostbyname($server);
  269. X        return undef unless @x;
  270. X        $serveraddr = $x[4];
  271. X    }
  272. X    $serverproc = pack($sockaddr, 2, $port, $serveraddr);
  273. X    unless (socket(S, 2, 1, 6)) {
  274. X        # XXX hardwired $AF_SOCKET, $SOCK_STREAM, 'tcp'
  275. X        # but who the heck would change these anyway? (:-)
  276. X        ($!) = ($!, close(S)); # close S while saving $!
  277. X        return undef;
  278. X    }
  279. X    unless (bind(S, $thisproc)) {
  280. X        ($!) = ($!, close(S)); # close S while saving $!
  281. X        return undef;
  282. X    }
  283. X    unless (connect(S, $serverproc)) {
  284. X        ($!) = ($!, close(S)); # close S while saving $!
  285. X        return undef;
  286. X    }
  287. X# We opened with the local address set to ANY, at this stage we know
  288. X# which interface we are using.  This is critical if our machine is
  289. X# multi-homed, with IP forwarding off, so fix-up.
  290. X    local($fam,$lport);
  291. X    ($fam,$lport,$thisaddr) = unpack($sockaddr, getsockname(S));
  292. X    $thisproc = pack($sockaddr, 2, 0, $thisaddr);
  293. X# end of post-connect fixup
  294. X    select((select(S), $| = 1)[0]);
  295. X    $next; # return symbol for switcharound
  296. X}
  297. X
  298. X## ($host, $port, $handle) = &chat'open_listen();
  299. X## opens a TCP port on the current machine, ready to be listened to
  300. X
  301. Xsub open_listen { ## public
  302. X
  303. X    *S = ++$next;
  304. X    local(*NS) = "__" . time;
  305. X    unless (socket(NS, 2, 1, 6)) {
  306. X        # XXX hardwired $AF_SOCKET, $SOCK_STREAM, 'tcp'
  307. X        # but who the heck would change these anyway? (:-)
  308. X        ($!) = ($!, close(NS));
  309. X        return undef;
  310. X    }
  311. X    unless (bind(NS, $thisproc)) {
  312. X        ($!) = ($!, close(NS));
  313. X        return undef;
  314. X    }
  315. X    unless (listen(NS, 1)) {
  316. X        ($!) = ($!, close(NS));
  317. X        return undef;
  318. X    }
  319. X    select((select(NS), $| = 1)[0]);
  320. X    local($family, $port, @myaddr) =
  321. X        unpack("S n C C C C x8", getsockname(NS));
  322. X    $S{"needs_accept"} = *NS; # so expect will open it
  323. X    (@myaddr, $port, $next); # returning this
  324. X}
  325. X
  326. X## $handle = &chat'open_proc("command","arg1","arg2",...);
  327. X## opens a /bin/sh on a pseudo-tty
  328. X
  329. Xsub open_proc { ## public
  330. X    local(@cmd) = @_;
  331. X
  332. X    *S = ++$next;
  333. X    local(*TTY) = "__TTY" . time;
  334. X    local($pty,$tty) = &_getpty(S,TTY);
  335. X    die "Cannot find a new pty" unless defined $pty;
  336. X    $pid = fork;
  337. X    die "Cannot fork: $!" unless defined $pid;
  338. X    unless ($pid) {
  339. X        close STDIN; close STDOUT; close STDERR;
  340. X        setpgrp(0,$$);
  341. X        if (open(DEVTTY, "/dev/tty")) {
  342. X            ioctl(DEVTTY,0x20007471,0);        # XXX s/b &TIOCNOTTY
  343. X            close DEVTTY;
  344. X        }
  345. X        open(STDIN,"<&TTY");
  346. X        open(STDOUT,">&TTY");
  347. X        open(STDERR,">&STDOUT");
  348. X        die "Oops" unless fileno(STDERR) == 2;    # sanity
  349. X        close(S);
  350. X        exec @cmd;
  351. X        die "Cannot exec @cmd: $!";
  352. X    }
  353. X    close(TTY);
  354. X    $next; # return symbol for switcharound
  355. X}
  356. X
  357. X# $S is the read-ahead buffer
  358. X
  359. X## $return = &chat'expect([$handle,] $timeout_time,
  360. X##     $pat1, $body1, $pat2, $body2, ... )
  361. X## $handle is from previous &chat'open_*().
  362. X## $timeout_time is the time (either relative to the current time, or
  363. X## absolute, ala time(2)) at which a timeout event occurs.
  364. X## $pat1, $pat2, and so on are regexs which are matched against the input
  365. X## stream.  If a match is found, the entire matched string is consumed,
  366. X## and the corresponding body eval string is evaled.
  367. X##
  368. X## Each pat is a regular-expression (probably enclosed in single-quotes
  369. X## in the invocation).  ^ and $ will work, respecting the current value of $*.
  370. X## If pat is 'TIMEOUT', the body is executed if the timeout is exceeded.
  371. X## If pat is 'EOF', the body is executed if the process exits before
  372. X## the other patterns are seen.
  373. X##
  374. X## Pats are scanned in the order given, so later pats can contain
  375. X## general defaults that won't be examined unless the earlier pats
  376. X## have failed.
  377. X##
  378. X## The result of eval'ing body is returned as the result of
  379. X## the invocation.  Recursive invocations are not thought
  380. X## through, and may work only accidentally. :-)
  381. X##
  382. X## undef is returned if either a timeout or an eof occurs and no
  383. X## corresponding body has been defined.
  384. X## I/O errors of any sort are treated as eof.
  385. X
  386. Xsub expect { ## public
  387. X    if ($_[0] =~ /$nextpat/) {
  388. X        *S = shift;
  389. X    }
  390. X    local($endtime) = shift;
  391. X
  392. X    $endtime += time if $endtime < 600_000_000;
  393. X    local($rmask, $nfound, $timeleft, $thisbuf);
  394. X    local($timeout,$eof) = (1,1);
  395. X    local($cases,$pattern,$action);
  396. X    local($caller) = caller;
  397. X    local($return,@return);
  398. X    local($returnvar) = wantarray ? '@return' : '$return';
  399. X    $cases = '';
  400. X
  401. X    if (defined $S{"needs_accept"}) { # is it a listen socket?
  402. X        local(*NS) = $S{"needs_accept"};
  403. X        delete $S{"needs_accept"};
  404. X        $S{"needs_close"} = *NS;
  405. X        unless(accept(S,NS)) {
  406. X            ($!) = ($!, close(S), close(NS));
  407. X            return undef;
  408. X        }
  409. X        select((select(S), $| = 1)[0]);
  410. X    }
  411. X
  412. X    ## strategy: create a giant block inside $cases
  413. X    $cases .= <<'ESQ';
  414. X    LOOP: {
  415. XESQ
  416. X    while (@_) {
  417. X        ($pattern,$action) = splice(@_,0,2);
  418. X        if ($pattern =~ /^eof$/i) {
  419. X            $cases .= <<"EDQ";
  420. X        if (\$eof) {
  421. X            $returnvar = do { package $caller; $action; };
  422. X            last LOOP;
  423. X        }
  424. XEDQ
  425. X            $eof = 0;
  426. X        } elsif ($pattern =~ /^timeout$/i) {
  427. X            $cases .= <<"EDQ";
  428. X        if (\$timeout) {
  429. X            $returnvar = do { package $caller; $action; };
  430. X            last LOOP;
  431. X        }
  432. XEDQ
  433. X            $timeout = 0;
  434. X        } else {
  435. X            $pattern =~ s#/#\\/#g;
  436. X            $cases .= <<"EDQ";
  437. X        if (\$S =~ /$pattern/) {
  438. X            \$S = \$';
  439. X            $returnvar = do { package $caller; $action; };
  440. X            last LOOP;
  441. X        }
  442. XEDQ
  443. X        }
  444. X    }
  445. X    $cases .= <<"EDQ" if $eof;
  446. X        if (\$eof) {
  447. X            $returnvar = undef;
  448. X            last LOOP;
  449. X        }
  450. XEDQ
  451. X    $cases .= <<"EDQ" if $timeout;
  452. X        if (\$timeout) {
  453. X            $returnvar = undef;
  454. X            last LOOP;
  455. X        }
  456. XEDQ
  457. X    $eof = $timeout = 0;
  458. X    $cases .= <<'ESQ';
  459. X        $rmask = "";
  460. X        vec($rmask,fileno(S),1) = 1;
  461. X        ($nfound, $rmask) =
  462. X             select($rmask, undef, undef, $endtime - time);
  463. X        if ($nfound) {
  464. X            "<nfound = $nfound>";
  465. X            $nread = sysread(S, $thisbuf, 1024);
  466. X            if( $chat'debug ){
  467. X                print STDERR "read $nread bytes: $thisbuf";
  468. X            }
  469. X            if ($nread > 0) {
  470. X                $S .= $thisbuf;
  471. X            } else {
  472. X                $eof++, redo LOOP; # any error is also eof
  473. X            }
  474. X        } else {
  475. X            $timeout++, redo LOOP; # timeout
  476. X        }
  477. X        redo LOOP;
  478. X    }
  479. XESQ
  480. X    eval $cases; die "$cases:\n$@" if $@;
  481. X    if (wantarray) {
  482. X        return @return;
  483. X    } else {
  484. X        return $return;
  485. X    }
  486. X}
  487. X
  488. X## &chat'print([$handle,] @data)
  489. X## $handle is from previous &chat'open().
  490. X## like print $handle @data
  491. X
  492. Xsub print { ## public
  493. X    if ($_[0] =~ /$nextpat/) {
  494. X        *S = shift;
  495. X    }
  496. X    print S @_;
  497. X    if( $chat'debug ){
  498. X        print STDERR "printed:";
  499. X        print STDERR @_;
  500. X    }
  501. X}
  502. X
  503. X## &chat'close([$handle,])
  504. X## $handle is from previous &chat'open().
  505. X## like close $handle
  506. X
  507. Xsub close { ## public
  508. X    if ($_[0] =~ /$nextpat/) {
  509. X         *S = shift;
  510. X    }
  511. X    close(S);
  512. X    if (defined $S{"needs_close"}) { # is it a listen socket?
  513. X        local(*NS) = $S{"needs_close"};
  514. X        delete $S{"needs_close"};
  515. X        close(NS);
  516. X    }
  517. X}
  518. X
  519. X# ($pty,$tty) = $chat'_getpty(PTY,TTY):
  520. X# internal procedure to get the next available pty.
  521. X# opens pty on handle PTY, and matching tty on handle TTY.
  522. X# returns undef if can't find a pty.
  523. X
  524. Xsub _getpty { ## private
  525. X    local($_PTY,$_TTY) = @_;
  526. X    $_PTY =~ s/^([^']+)$/(caller)[$[]."'".$1/e;
  527. X    $_TTY =~ s/^([^']+)$/(caller)[$[]."'".$1/e;
  528. X    local($pty,$tty);
  529. X    for $bank (112..127) {
  530. X        next unless -e sprintf("/dev/pty%c0", $bank);
  531. X        for $unit (48..57) {
  532. X            $pty = sprintf("/dev/pty%c%c", $bank, $unit);
  533. X            open($_PTY,"+>$pty") || next;
  534. X            select((select($_PTY), $| = 1)[0]);
  535. X            ($tty = $pty) =~ s/pty/tty/;
  536. X            open($_TTY,"+>$tty") || next;
  537. X            select((select($_TTY), $| = 1)[0]);
  538. X            system "stty nl>$tty";
  539. X            return ($pty,$tty);
  540. X        }
  541. X    }
  542. X    undef;
  543. X}
  544. X
  545. X1;
  546. END_OF_FILE
  547.   if test 8328 -ne `wc -c <'mserv-3.1/chat2.pl'`; then
  548.     echo shar: \"'mserv-3.1/chat2.pl'\" unpacked with wrong size!
  549.   fi
  550.   # end of 'mserv-3.1/chat2.pl'
  551. fi
  552. if test -f 'mserv-3.1/do_report.pl' -a "${1}" != "-c" ; then 
  553.   echo shar: Will not clobber existing file \"'mserv-3.1/do_report.pl'\"
  554. else
  555.   echo shar: Extracting \"'mserv-3.1/do_report.pl'\" \(6395 characters\)
  556.   sed "s/^X//" >'mserv-3.1/do_report.pl' <<'END_OF_FILE'
  557. X#!/usr/local/bin/perl
  558. X# do_report.pl -- run mail server report
  559. X# SCCS Status     : @(#)@ do_report    1.13
  560. X# Author          : Johan Vromans
  561. X# Created On      : Sat May  2 14:15:16 1992
  562. X# Last Modified By: Johan Vromans
  563. X# Last Modified On: Fri Dec 25 16:23:12 1992
  564. X# Update Count    : 82
  565. X# Status          : OK
  566. X
  567. X$my_name = "do_report";
  568. X$my_version = "1.13";
  569. X#
  570. X################ Common stuff ################
  571. X
  572. X$libdir = $ENV{"MSERVLIB"} || "/usr/local/lib/mserv";
  573. Xunshift (@INC, $libdir);
  574. X
  575. X################ Presets ################
  576. X
  577. X@args = ();
  578. X
  579. X################ Options handling ################
  580. X
  581. X&options if @ARGV > 0 && $ARGV[0] =~ /^-+[^-]+/;
  582. Xrequire "ms_common.pl";
  583. Xprint ($my_package, " [", $my_name, " ", $my_version, "]\n")
  584. X    if $opt_ident;
  585. Xif ( @ARGV > 0 ) {
  586. X    @dest = @ARGV;
  587. X}
  588. Xelse {
  589. X    @dest = ( $mserv_owner );
  590. X}
  591. X
  592. X################ Main ################
  593. X
  594. X$tmpfile_prefix = $tmpdir . "/rpt$$.";
  595. X$rpt = $tmpfile_prefix . "rpt";
  596. X$err = $tmpfile_prefix . "err";
  597. X$tmp = $tmpfile_prefix . "tmp";
  598. X$oldlog = $logfile . ".o";
  599. X
  600. Xif ( $opt_collect ) {
  601. X    # Seize logfile.
  602. X    &die ("Found $oldlog, will not proceed") if -s $oldlog;
  603. X    &unlink ($oldlog);
  604. X
  605. X    if ( &rename ($logfile, $oldlog) ) {
  606. X    open (LOG, ">".$logfile) && close (LOG);
  607. X    }
  608. X    else {
  609. X    &die ("Cannot rename $logfile to $oldlog [$!]");
  610. X    }
  611. X
  612. X    # Run report.
  613. X    &system ("$libdir/report @args $oldlog >$rpt 2>$err")
  614. X    if $opt_usage || $opt_errors;
  615. X}
  616. Xelse {
  617. X    &system ("$libdir/report @args >$rpt 2>$err")
  618. X    if $opt_usage || $opt_errors;
  619. X}
  620. X
  621. Xopen (RPT, ">>$rpt");
  622. Xprint RPT ($^L) if -s RPT;    # Insert form-feed if needed.
  623. X
  624. Xif ( $opt_collect ) {
  625. X
  626. X    # Append to accumulating data and compress (again).
  627. X    if ( -f $logfile . ".cum.Z") {
  628. X    &system ("uncompress $logfile.cum");
  629. X    &system ("cat $oldlog >> $logfile.cum");
  630. X    &unlink ($oldlog);
  631. X    &system ("compress $logfile.cum");
  632. X    }
  633. X    else {
  634. X    &system ("cat $oldlog >> $logfile.cum");
  635. X    &unlink ($oldlog);
  636. X    # &system ("compress $logfile.cum");
  637. X    }
  638. X}
  639. X
  640. Xif ( ($opt_ftp || $opt_ftpclean) && $ftp && $ftp_cache ) {
  641. X
  642. X    require 'find.pl';
  643. X
  644. X    $ftp_keep = $opt_ftpkeep if defined $opt_ftpkeep;
  645. X    $files = 0;
  646. X    $preflen = length ($ftp_cache) + 1;
  647. X    *wanted = *ftw_ftp;
  648. X    select (RPT);
  649. X    $^ = 'FTP_TOP';
  650. X    $~ = 'FTP_OUT';
  651. X    $: = " /";
  652. X    &find ($ftp_cache);
  653. X}
  654. X
  655. Xclose (RPT);
  656. X
  657. X&cleanup;
  658. X
  659. X################ Subroutines ################
  660. X
  661. Xsub cleanup {
  662. X    &mail ($err, "ERRORS from Mail Server") if -s $err;
  663. X    &mail ($rpt, "Mail Server Report") if -s $rpt;
  664. X    &unlink ($rpt, $err, $tmp);
  665. X}
  666. X
  667. Xsub unlink {
  668. X    local (@files) = @_;
  669. X    print STDERR ("+ unlink @files\n") if $opt_trace;
  670. X    unlink (@files);
  671. X}
  672. X
  673. Xsub rename {
  674. X    local ($old, $new) = @_;
  675. X    print STDERR ("+ rename $old $new\n") if $opt_trace;
  676. X    rename ($old, $new);
  677. X}
  678. X
  679. Xsub system {
  680. X    local ($cmd) = (@_);
  681. X    local ($ret);
  682. X    print STDERR ("+ $cmd\n") if $opt_trace;
  683. X    $ret = system ($cmd);
  684. X    &die (sprintf ("Return 0x%x from \"$cmd\"", $ret))
  685. X    unless $ret == 0;
  686. X    $ret;
  687. X}
  688. X
  689. Xformat FTP_TOP =
  690. XFiles in FTP cache @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  691. X$ftp_cache
  692. X
  693. X  Timestamp     Age*  Size  Filename   (* means: file has been removed)
  694. X--------------  ----  ----  -------------------------------------------
  695. X.
  696. Xformat FTP_OUT =
  697. X@<<<<<<<<<<<<< @>>@@>>>>>K  ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  698. X$timestamp, $age, $tag, $size, $fname
  699. X~~                            ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  700. X$fname
  701. X.
  702. X
  703. Xsub ftw_ftp {
  704. X    @st = stat ($_);
  705. X    if ( @st[2] & 0100000 ) {
  706. X    $size = int (($st[7] + 1023) / 1024);
  707. X    $age = int (-A _ );
  708. X    @tm = localtime ($st[9]);
  709. X    $tag = '';
  710. X    if ( $opt_ftpclean && $ftp_keep > 0 && ( $age > $ftp_keep ) ) {
  711. X        if (unlink($_)) {
  712. X        $tag = '*';
  713. X        }
  714. X        else {
  715. X        $_ .= " (not removed: $!)";
  716. X        }
  717. X    }
  718. X    $timestamp = sprintf ("%02d/%02d/%02d %02d:%02d", 
  719. X                  $tm[5], 1+$tm[4], $tm[3], $tm[2], $tm[1]);
  720. X    $fname = substr($dir,$preflen) . '/' . $_;
  721. X    write;
  722. X    }
  723. X}
  724. X
  725. Xsub warn {
  726. X    local ($msg) = (@_);
  727. X    warn ($my_name . ": " . $msg . "\n");
  728. X}
  729. X
  730. Xsub die {
  731. X    &warn;
  732. X    &cleanup;
  733. X    exit (1);
  734. X}
  735. X
  736. Xsub mail {
  737. X    local ($file, $subj) = @_;
  738. X    local ($cmd) = "$sendmail '" . join("' '", @dest) . "'";
  739. X
  740. X    # DO NOT USE '&die' in this routine.
  741. X
  742. X    print STDERR ("+ |", $cmd, "\n") if $opt_trace;
  743. X
  744. X    open (MAIL, "|" . $cmd)
  745. X    || die ("$my_name: Cannot invoke $cmd [$!]\n");
  746. X    print MAIL ("To: ", join(", ", @dest), "\n",
  747. X        "Subject: $subj\n",
  748. X        "\n");
  749. X    if ( open (FILE, $file) ) {
  750. X    while ( <FILE> ) {
  751. X        print MAIL $_;
  752. X    }
  753. X    close (FILE);
  754. X    }
  755. X    close (MAIL);
  756. X    die ("$my_name: Mail error $?\n") if $?;
  757. X}
  758. X
  759. Xsub options {
  760. X    require "newgetopt.pl";
  761. X    $opt_ident = $opt_help = 0;
  762. X    $opt_errors = $opt_usage = $opt_full = 0;
  763. X    $opt_collect = $opt_trace = $opt_noupdate = 0;
  764. X    if ( !&NGetOpt ("ident", "errors", "usage", "full", "collect",
  765. X            "config=s", "since=s", "noupdate",
  766. X            "ftp", "ftpclean", "ftpkeep=i",
  767. X            "trace", "help")
  768. X    || $opt_help ) {
  769. X    &usage;
  770. X    }
  771. X    $opt_errors |= $opt_full;
  772. X    $opt_usage |= $opt_full;
  773. X    $opt_ftp |= $opt_full;
  774. X    $opt_usage = 1 unless $opt_errors || $opt_ftp || $opt_ftpclean;
  775. X    unshift (@args, "-full") if $opt_usage && $opt_errors;
  776. X    unshift (@args, "-errors") if $opt_errors && !$opt_usage;
  777. X    unshift (@args, "-since", $opt_since) if defined $opt_since;
  778. X    unshift (@args, "-noupdate") if $opt_noupdate;
  779. X    unshift (@args, "-usage") if $opt_usage && !$opt_errors;
  780. X    undef $opt_errors, $opt_full, $opt_usage;
  781. X    $config_file = $opt_config if defined $opt_config;
  782. X}
  783. X
  784. Xsub usage {
  785. X    require "ms_common.pl";
  786. X    print STDERR <<EndOfUsage;
  787. X$my_package [$my_name $my_version]
  788. X
  789. XUsage: $my_name [options] [ recipients... ]
  790. X
  791. XOptions:
  792. X    -config XX    use alternate config file
  793. X    -usage    generate usage report
  794. X    -ftp    show files in FTP cache
  795. X    -full    generate report for usage, errors and ftp
  796. X    -ftpclean    cleanup old files in FTP cache (implies -ftp)
  797. X    -ftpkeep NN number of days a file is to be kept in the FTP cache (default: $ftp_keep)
  798. X    -since FILE    only error messages newer than FILE
  799. X        (FILE date will be updated upon successful completion)
  800. X    -noupdate    do not update FILE date
  801. X    -collect    collect and cleanup logfile data
  802. X    -help    this message
  803. X    -trace    show commands
  804. X    -ident    print identification
  805. X
  806. XDefault action is to generate a usage report, and to mail it to the
  807. Xrecipients (default: $mserv_owner).
  808. XEndOfUsage
  809. X    exit (1);
  810. X}
  811. END_OF_FILE
  812.   if test 6395 -ne `wc -c <'mserv-3.1/do_report.pl'`; then
  813.     echo shar: \"'mserv-3.1/do_report.pl'\" unpacked with wrong size!
  814.   fi
  815.   # end of 'mserv-3.1/do_report.pl'
  816. fi
  817. if test -f 'mserv-3.1/dr_mail.pl' -a "${1}" != "-c" ; then 
  818.   echo shar: Will not clobber existing file \"'mserv-3.1/dr_mail.pl'\"
  819. else
  820.   echo shar: Extracting \"'mserv-3.1/dr_mail.pl'\" \(7856 characters\)
  821.   sed "s/^X//" >'mserv-3.1/dr_mail.pl' <<'END_OF_FILE'
  822. X# dr_mail.pl -- handle request via email
  823. X# SCCS Status     : @(#)@ dr_mail.pl    3.5
  824. X# Author          : Johan Vromans
  825. X# Created On      : Thu Jun  4 22:22:20 1992
  826. X# Last Modified By: Johan Vromans
  827. X# Last Modified On: Sat Dec 12 01:52:22 1992
  828. X# Update Count    : 25
  829. X# Status          : OK
  830. X
  831. Xsub mail_request {
  832. X
  833. X    local ($rcpt, $address, $uunote, $request, $file, $encoding, $limit, $parts) = @_;
  834. X
  835. X    if ( $opt_debug ) {
  836. X    print STDERR ("&mail_request(rcpt=$rcpt, address=$address, ",
  837. X              "request=$request,\n",
  838. X              "    file=$file,\n",
  839. X              "    encoding=$encoding, limit=$limit, parts=$parts,",
  840. X              " remove=$remove_file)\n");
  841. X    }
  842. X
  843. X    # This routine handles the requests.
  844. X    # Handling includes encoding, splitting and transmitting.
  845. X
  846. X    &check_file ($file, 0);
  847. X
  848. X    local ($fname);        # Basename of file to send
  849. X    local ($cmd);        # Command to handle encoding
  850. X    local ($code) = '';        # Verbose description of encoding
  851. X    local ($files);        # Number of files to send
  852. X    local (@files);        # List of files to send
  853. X    local ($the_file);        # Current part be send
  854. X    local ($the_part);        # Sequence number thereof
  855. X    local ($size);        # Size of chunk
  856. X    local ($tmpfile_prefix) = $opt_keep || "$tmpdir/drq$$.";
  857. X    local ($Dtmpdir);        # Private dir for Dumas uue
  858. X    local ($opt_nolog) = $opt_nolog;
  859. X    local ($opt_keep) = $opt_keep;
  860. X    local ($compressed) = '';    # we compressed it
  861. X
  862. X    if ( $address eq "" || $address eq "-" ) {
  863. X    # Use this e.g. to include an encoded archive in email.
  864. X    $limit = "0";
  865. X    $opt_nolog = 1;        # Local.
  866. X    $address = "";
  867. X    }
  868. X    $limit = 32*1024 if $limit eq "";
  869. X    if ( $limit ne "0" ) {
  870. X    # Limit must be between 10 and 256K, with 32K default.
  871. X    $limit =  $`*1024 if $limit =~ /K$/;
  872. X    $limit =  10*1024 if $limit <  10*1024;
  873. X    $limit = 256*1024 if $limit > 256*1024;
  874. X    }
  875. X    print STDERR ("Using limit = $limit\n") if $opt_debug;
  876. X
  877. X    $encoding = $default_encoding unless defined $encoding;
  878. X
  879. X    # Compress first, if requested.
  880. X    if ( $encoding =~ /^[^ap].*z$/i && $compress ) {
  881. X    local ($tmp) = &fttemp;
  882. X    print STDERR ("Using compression\n") if $opt_debug;
  883. X    &system ("$compress < $file > $tmp");
  884. X    if ( $remove_file ) {
  885. X        print STDERR ("Unlinking $file\n") if $opt_debug;
  886. X        unlink ($file);
  887. X    }
  888. X    $remove_file = 1;
  889. X    $file = $tmp;
  890. X    $code = 'compressed,';
  891. X    $compressed = chop ($encoding);
  892. X    }
  893. X
  894. X    # Get dir and basename of the requested file.
  895. X    local ($dir, $fname) = &fnsplit ($file);
  896. X
  897. X    # Prepare the command to use.
  898. X    # The result of command should be the encoded file, written
  899. X    # to standard output.
  900. X
  901. X    if ( $encoding =~ /^u/i ) {
  902. X
  903. X    # Standard UU encoding.
  904. X    $code .= "uuencoded";
  905. X    $cmd = "$uuencode $file '$fname'";
  906. X    }
  907. X    elsif ( $encoding =~ /^x/i ) {
  908. X
  909. X    # Modified UU encoding.
  910. X    $code .= "xxencoded";
  911. X    $cmd = "$xxencode $file '$fname'";
  912. X    }
  913. X    elsif ( $encoding =~ /^d/i ) {
  914. X
  915. X    # Dumas' modified UU encoding.
  916. X    # Uue has a built-in facility to generate multi-part
  917. X    # files. The customer wants to use this feature...
  918. X    local ($split) = '';
  919. X    $code .= "uue-encoded";
  920. X    $split = '-' . (int ($limit / 63) - 2) if $limit;
  921. X
  922. X    # Prepare a private directory for uue to work in.
  923. X    $Dtmpdir = "$tmpdir/D$$";
  924. X    &system ("rm -fr $Dtmpdir");
  925. X    &system ("mkdir $Dtmpdir");
  926. X    &symlink ($file, "$Dtmpdir/$fname");
  927. X    $cmd = "cd $Dtmpdir; $uue $split '$fname'";
  928. X    }
  929. X    elsif ( $encoding =~ /^[pa]/i || $encoding eq "" ) {
  930. X    
  931. X    # No decoding.
  932. X    $encoding = "A";
  933. X    $code .= "ascii";
  934. X    $cmd = "";
  935. X    }
  936. X    else {
  937. X
  938. X    # Binary-to-Ascii encoding.
  939. X    $encoding = "B";
  940. X    $code .= "btoa encoded";
  941. X    $cmd = "$btoa < $file";
  942. X    }
  943. X    print STDERR ("Using encoding = $encoding ($code)\n") if $opt_debug;
  944. X
  945. X    if ( $encoding eq "A" && ($limit == 0 || (-s $file <= $limit)) ) {
  946. X    # A simple ascii file smaller than $limit -> use it.
  947. X    @files = ($file);
  948. X    $opt_keep = 1;        # Local copy!
  949. X    }
  950. X    elsif ( $encoding eq "D" ) {
  951. X    local ($path) = ($Dtmpdir);
  952. X
  953. X    # Encode and split.
  954. X    &system ($cmd);
  955. X
  956. X    # Now gather all the parts, and tally them.
  957. X    opendir (DIR, $path)
  958. X        || &die ("Cannot read $path/ [$!]");
  959. X    @files = sort (grep (/\.u[a-z][a-z]$/o, readdir (DIR)));
  960. X    close (DIR);
  961. X    foreach ( @files ) {
  962. X        # Note: $_ is a *ref* into @files!
  963. X        $_ = "$path/$_";
  964. X    }
  965. X    }
  966. X    else {
  967. X    # It is tempting to use 'split' to cut the request into
  968. X    # pieces. Until recently, I did.
  969. X    # Splitting ourselves makes it possible to split ascii files
  970. X    # also. In this case we can spare another process.
  971. X    local ($suffix) = "aa";
  972. X    local ($size) = $limit + 1;
  973. X
  974. X    if ( $cmd ) {
  975. X        print STDERR ("+ $cmd|\n") if $opt_trace;
  976. X        open (FEED, "$cmd|")
  977. X        || die ("Error opening pipe \"$cmd|\" [$!]\n");
  978. X    }
  979. X    else {
  980. X        print STDERR ("+ <$file\n") if $opt_trace;
  981. X        open (FEED, "$file")
  982. X        || die ("Error opening file \"$file\" [$!]\n");
  983. X    }
  984. X
  985. X    @files = ();
  986. X    while ( <FEED> ) {
  987. X        if ( $limit > 0 && ($size += length ($_)) > $limit ) {
  988. X        close (OUT);
  989. X        open (OUT, ">$tmpfile_prefix$suffix")
  990. X            || die ("Cannot create $tmpfile_prefix$suffix: [$!]\n");
  991. X        push (@files, "$tmpfile_prefix$suffix");
  992. X        $size = length ($_);
  993. X        $suffix++;
  994. X        }
  995. X        print OUT;
  996. X    }
  997. X    close (OUT);
  998. X    close (FEED);
  999. X    }
  1000. X
  1001. X    $files = @files;
  1002. X
  1003. X    if ( $opt_debug ) {
  1004. X    if ( $files > 1 ) {
  1005. X        print STDERR ("Sending ", $files, " files: ",
  1006. X              $files[0], " .. ", $files[$#files], "\n");
  1007. X    }
  1008. X    elsif ( $files == 1 ) {
  1009. X        print STDERR ("Sending file: ", $files[0], "\n");
  1010. X    }
  1011. X    else {
  1012. X        printf STDERR ("No files to send.\n");
  1013. X    }    
  1014. X    }
  1015. X
  1016. X    # Format for "part xx of yy" message. Keep things sortable.
  1017. X    local ($part_fmt) = ( $files == 1 ) ? "complete" : 
  1018. X    "part %0" . length("$files") . "d of %d";
  1019. X
  1020. X    $the_part = 0;
  1021. X    foreach $the_file ( @files ) {
  1022. X
  1023. X    $the_part++;
  1024. X    # Form "part xx of yy" message.
  1025. X    $part = sprintf ($part_fmt, $the_part, $files);
  1026. X
  1027. X    if ( $parts && $parts !~ /\b$the_part\b/ ) {
  1028. X        unlink ($the_file) unless $opt_keep;
  1029. X        print STDERR ("Skipping part $the_part (not requested).\n")
  1030. X        if $opt_debug;
  1031. X        next;
  1032. X    }
  1033. X    else {
  1034. X        print STDERR ("Sending $part.\n")
  1035. X        if $opt_debug;
  1036. X    }
  1037. X
  1038. X    # Send it.
  1039. X    if ( open (PART, $the_file) ) {
  1040. X        if ( $address eq "" ) {
  1041. X        $size = © (*STDOUT);
  1042. X        }
  1043. X        else {
  1044. X        # Suppress sleep after the last part.
  1045. X        local ($mailer_delay) = $mailer_delay;
  1046. X        undef $mailer_delay if $the_part == $files;
  1047. X        $size = &xfer;
  1048. X        }
  1049. X        close (PART);
  1050. X    }
  1051. X
  1052. X    # Write a log message.
  1053. X    &writelog ("M \"$address\" $request $encoding$compressed$the_part".
  1054. X           "/$files $size")
  1055. X        if $address ne "";
  1056. X
  1057. X    unlink ($the_file) unless $opt_keep;
  1058. X    }
  1059. X
  1060. X    &system ("rm -fr $Dtmpdir") if $encoding eq "D" && !$opt_keep;
  1061. X    if ( $remove_file ) {
  1062. X    print STDERR ("Unlinking $file\n") if $opt_debug;
  1063. X    unlink ($file);
  1064. X    }
  1065. X}
  1066. X
  1067. Xsub headers {
  1068. X    local (*FILE, $full) = @_;
  1069. X
  1070. X    # Provide some RFC822 compliant headers.
  1071. X
  1072. X    local ($size) = 0;
  1073. X
  1074. X    if ( defined $sender ) {
  1075. X    print FILE "$sender\n";
  1076. X    $size += length ($sender) + 1;
  1077. X    }
  1078. X
  1079. X    $ln = "To: $address\n";
  1080. X    $ln .= "Subject: $request ($part) $code\n";
  1081. X    $ln .= "Precedence: bulk\n";
  1082. X    $ln .= join ("\n", @x_headers) . "\n" if defined @x_headers;
  1083. X    print FILE ($ln, "\n");
  1084. X    $size += length ($ln) + 1;
  1085. X}
  1086. X
  1087. Xsub copy {
  1088. X    local (*FILE) = shift (@_);
  1089. X    local ($size);
  1090. X    local ($ln);
  1091. X
  1092. X    $ln = "Request: $request\n\n".
  1093. X    "------ begin of $fname -- $code -- $part ------\n";
  1094. X    $size = length ($ln);
  1095. X    print FILE $ln;
  1096. X    while ( <PART> ) {
  1097. X    print FILE $_;
  1098. X    $size += length ($_);
  1099. X    }
  1100. X    $ln = "------ end of $fname -- $code -- $part ------\n";
  1101. X    print FILE $ln;
  1102. X    $size + length ($ln);
  1103. X}
  1104. X
  1105. Xsub xfer {
  1106. X
  1107. X    # Send the file via e-mail.
  1108. X    local ($size);
  1109. X
  1110. X    if ( $opt_nomail ) {
  1111. X    print STDERR "[Would call \"$chunkmail\"]\n";
  1112. X    &headers (*STDOUT, 0);
  1113. X    }
  1114. X    elsif ( open (MAILER, "|$chunkmail '$address'") ) {
  1115. X    $size = &headers (*MAILER, 0);
  1116. X    $size += © (*MAILER);
  1117. X    close MAILER;
  1118. X
  1119. X    # Allow system to stabilize.
  1120. X    sleep ($mailer_delay) if defined $mailer_delay;
  1121. X    }
  1122. X    $size;
  1123. X}
  1124. X
  1125. X1;
  1126. END_OF_FILE
  1127.   if test 7856 -ne `wc -c <'mserv-3.1/dr_mail.pl'`; then
  1128.     echo shar: \"'mserv-3.1/dr_mail.pl'\" unpacked with wrong size!
  1129.   fi
  1130.   # end of 'mserv-3.1/dr_mail.pl'
  1131. fi
  1132. if test -f 'mserv-3.1/mlistener.pl' -a "${1}" != "-c" ; then 
  1133.   echo shar: Will not clobber existing file \"'mserv-3.1/mlistener.pl'\"
  1134. else
  1135.   echo shar: Extracting \"'mserv-3.1/mlistener.pl'\" \(4924 characters\)
  1136.   sed "s/^X//" >'mserv-3.1/mlistener.pl' <<'END_OF_FILE'
  1137. X#!/usr/local/bin/perl
  1138. X# mlistener.pl -- make listener.c
  1139. X# SCCS Status     : @(#)@ mlistener.pl    1.7
  1140. X# Author          : Johan Vromans
  1141. X# Created On      : Sun May 31 14:22:56 1992
  1142. X# Last Modified By: Johan Vromans
  1143. X# Last Modified On: Wed Dec 23 23:03:16 1992
  1144. X# Update Count    : 29
  1145. X# Status          : Unknown, Use with caution!
  1146. X
  1147. X$my_name = "mlistener.pl";
  1148. X$my_version = "1.7";
  1149. X#
  1150. X################ Common stuff ################
  1151. X
  1152. X$libdir = $ENV{"MSERVLIB"} || "/usr/local/lib/mserv";
  1153. X
  1154. X################ Options handling ################
  1155. X
  1156. X$opt_verbose = $opt_ident = $opt_help = 0;
  1157. X$opt_setruid = $opt_setenv = $opt_uid = 0;
  1158. X$opt_nosetruid = $opt_nosetenv = $opt_nouid = 0;
  1159. X&options if @ARGV > 0 && $ARGV[0] =~ /^-+[^-]+/;
  1160. Xrequire "./ms_common.pl";    # USE CURRENT DIR, NOT LIBDIR!
  1161. Xprint STDERR ($my_package, " [", $my_name, " ", $my_version, "]\n")
  1162. X    if $opt_ident || $opt_verbose;
  1163. X
  1164. X################ Main ################
  1165. X
  1166. X$mserv_uid = (getpwnam ($mserv_owner))[2];
  1167. Xdie ("Cannot get UID for user $mserv_owner\n") unless defined $mserv_uid;
  1168. X
  1169. Xif ( $opt_verbose ) {
  1170. X    print STDERR ("Using ", $have_setruid ? "setruid system call" :
  1171. X          "'su' program", ".\n");
  1172. X    print STDERR ("Using setenv library call.\n")
  1173. X    if $have_setruid && $have_setenv;
  1174. X    print STDERR ("Change to UID $mserv_uid.\n")
  1175. X    if $have_setruid && $use_uid;
  1176. X}
  1177. X
  1178. X$have_setruid |= $opt_setruid;
  1179. X$have_setruid = 0 if $opt_nosetruid;
  1180. X$have_setenv |= $opt_setenv;
  1181. X$have_setenv = 0 if $opt_nosetenv || !$have_setruid;
  1182. X$use_uid |= $opt_uid;
  1183. X$use_uid = 0 if $opt_nouid || !$have_setruid;
  1184. X
  1185. Xrequire "ctime.pl";
  1186. Xchop ($ctime = &ctime(time));
  1187. X$uid = $use_uid ? ", uid = $mserv_uid" : "";
  1188. X$opt = "";
  1189. X$opt .= " setruid" if $have_setruid;
  1190. X$opt .= " setenv" if $have_setenv;
  1191. X$opt .= " useuid" if $use_uid;
  1192. X
  1193. Xprint <<EOD;
  1194. X/* listener - receives mails and passes them to the mail server */
  1195. X
  1196. Xstatic char *SCCS_id[] = 
  1197. X    {"@(#)@ Generated by mlistener.pl 1.7 on $ctime",
  1198. X     "@(#)@ Configuration:",
  1199. X     "@(#)@     Server  = $mserv_owner$uid",
  1200. X     "@(#)@     Process = $libdir/process",
  1201. X     "@(#)@     Options =$opt"};
  1202. X
  1203. X#include <stdio.h>
  1204. XEOD
  1205. Xprint <<EOD if $have_setruid && !$use_uid;
  1206. X#include <pwd.h>
  1207. XEOD
  1208. Xprint <<EOD if $have_setruid;
  1209. Xint setruid();
  1210. XEOD
  1211. Xprint <<EOD if $have_setruid && !$use_uid;
  1212. Xint setrgid();
  1213. XEOD
  1214. Xprint <<EOD if $have_setenv;
  1215. Xint setenv();
  1216. XEOD
  1217. Xprint <<EOD;
  1218. X
  1219. X/* In an attempt to leave some useful tracks upon failure, 
  1220. X * we're gonna exit with special values.
  1221. X */
  1222. X#define abend(i)    exit(88+(i))
  1223. X
  1224. Xint chdir();
  1225. X
  1226. Xmain (argc, argv)
  1227. Xint argc;
  1228. Xchar *argv[];
  1229. X{
  1230. XEOD
  1231. Xif ( $have_setruid && $use_uid || $have_setruid ) {
  1232. X    print <<EOD;
  1233. X    argv[0] = "process";
  1234. XEOD
  1235. X}
  1236. Xif ( $have_setruid && $use_uid ) {
  1237. X    print <<EOD;
  1238. X    /* Change identity. */
  1239. X    if (setruid ($mserv_uid) < 0) abend (1);
  1240. XEOD
  1241. X    print <<EOD if $have_setenv;
  1242. X    setenv ("USER", "$mserv_owner", 1);
  1243. X    setenv ("LOGNAME", "$mserv_owner", 1);
  1244. X    setenv ("HOME", "/tmp", 1);
  1245. XEOD
  1246. X    print <<EOD;
  1247. X    if (chdir ("/tmp") < 0) abend (3);
  1248. X
  1249. X    /* Execute the real listener */
  1250. X    return execv ("$libdir/process", argv);
  1251. X    abend (4);
  1252. XEOD
  1253. X}
  1254. Xelsif ( $have_setruid ) {
  1255. X    print <<EOD;
  1256. X    struct passwd *pw;
  1257. X
  1258. X    /* Get info from system */
  1259. X    pw = getpwnam ("$mserv_owner");
  1260. X    if ( pw == NULL ) {
  1261. X      perror ("getpwnam");
  1262. X      exit (70);            /* Internal software error */
  1263. X    }
  1264. X
  1265. X    /* Change identity. */
  1266. X    if (setruid (pw->pw_uid) < 0) abend (1);
  1267. X    if (setrgid (pw->pw_gid) < 0) abend (2);
  1268. XEOD
  1269. X    print <<EOD if $have_setenv;
  1270. X    setenv ("USER", pw->pw_name, 1);
  1271. X    setenv ("LOGNAME", pw->pw_name, 1);
  1272. X    setenv ("HOME", pw->pw_dir, 1);
  1273. XEOD
  1274. X    print <<EOD;
  1275. X    if (chdir (pw->pw_dir) < 0) abend (3);
  1276. X
  1277. X    /* Execute the real listener */
  1278. X    return execv ("$libdir/process", argv);
  1279. X    abend (4);
  1280. XEOD
  1281. X}
  1282. Xelse {
  1283. X    print <<EOD;
  1284. X    /* NOTE: arbitrary limits ahead! */
  1285. X    char *args[64];
  1286. X    char cmd[512];
  1287. X    int i = 0;
  1288. X    args[i++] = "su";
  1289. X    args[i++] = "$mserv_owner";
  1290. X    args[i++] = "-c";
  1291. X    args[i++] = strcpy (cmd, "$libdir/process");
  1292. X    argv++;
  1293. X    while ( *argv ) {
  1294. X        strcat (cmd, " ");
  1295. X        strcat (cmd, *argv++);
  1296. X    }
  1297. X
  1298. X    /* Become root so we can so "su" w/o asking */
  1299. X    if (setuid (0) < 0) abend (10);
  1300. X    chdir ("/tmp");
  1301. X
  1302. X    /* Execute the real listener via "su" */
  1303. X    return execv ("/bin/su", args);
  1304. X    abend (11);
  1305. XEOD
  1306. X}
  1307. Xprint "}\n";
  1308. X
  1309. X################ Subroutines ################
  1310. X
  1311. Xsub options {
  1312. X    require "newgetopt.pl";
  1313. X    if ( !&NGetOpt ("setenv", "setruid", "nosetenv", "nosetruid",
  1314. X            "uid", "nouid", "config=s",
  1315. X            "verbose", "ident", "help")
  1316. X    || $opt_help
  1317. X    || (@ARGV > 0)) {
  1318. X    &usage;
  1319. X    }
  1320. X    $config_file = $opt_config if defined $opt_config;
  1321. X}
  1322. X
  1323. Xsub usage {
  1324. X    require "./ms_common.pl";
  1325. X    print STDERR <<EndOfUsage;
  1326. X$my_package [$my_name $my_version]
  1327. X
  1328. XUsage: $my_name [-help] [-ident]
  1329. X
  1330. XOptions:
  1331. X    -config XX      use alternate config file
  1332. X    -[no]setruid  use (do not use) setruid system call
  1333. X    -[no]setenv      use (do not use) setenv library call
  1334. X    -help      this message
  1335. X    -ident      print identification
  1336. X    -verbose      supply verbose information
  1337. XEndOfUsage
  1338. X    exit (1);
  1339. X}
  1340. END_OF_FILE
  1341.   if test 4924 -ne `wc -c <'mserv-3.1/mlistener.pl'`; then
  1342.     echo shar: \"'mserv-3.1/mlistener.pl'\" unpacked with wrong size!
  1343.   fi
  1344.   # end of 'mserv-3.1/mlistener.pl'
  1345. fi
  1346. if test -f 'mserv-3.1/pr_ftp.pl' -a "${1}" != "-c" ; then 
  1347.   echo shar: Will not clobber existing file \"'mserv-3.1/pr_ftp.pl'\"
  1348. else
  1349.   echo shar: Extracting \"'mserv-3.1/pr_ftp.pl'\" \(5633 characters\)
  1350.   sed "s/^X//" >'mserv-3.1/pr_ftp.pl' <<'END_OF_FILE'
  1351. X# pr_ftp.pl -- mail server support for FTP
  1352. X# SCCS Status     : @(#)@ pr_ftp.pl    1.6
  1353. X# Author          : Johan Vromans
  1354. X# Created On      : Sat Dec  5 01:06:44 1992
  1355. X# Last Modified By: Johan Vromans
  1356. X# Last Modified On: Thu Dec 31 16:23:04 1992
  1357. X# Update Count    : 35
  1358. X# Status          : Unknown, Use with caution!
  1359. X
  1360. X# This is the Squirrel Mail Server interface to the ftp.pl package.
  1361. X
  1362. Xrequire "$libdir/ftp.pl";
  1363. X
  1364. X&ftp'debug (1);        #';
  1365. X
  1366. Xsub ftp_connect {
  1367. X    local ($host, $user, $pass) = @_;
  1368. X
  1369. X    print STDOUT ("FTP Command execution:\n",
  1370. X          "    OPEN $host\n");
  1371. X
  1372. X    &ftp'close if $ftphost;            #';
  1373. X    &ftp'open ($host, 21, 0, 2);        #';
  1374. X    &ftp'login ($user, $pass);            #';
  1375. X    $ftphost = $host;
  1376. X}
  1377. X
  1378. Xsub ftp_get {
  1379. X    local ($file) = @_;
  1380. X
  1381. X    # See if a given file exists on the FTP site, and if a valid
  1382. X    # copy exists in the local ftp cache.
  1383. X    # Returns 
  1384. X    #   the name of the file in the cache, if it is valid
  1385. X    #   tmpname    if no valid file in cache, or the cache could not
  1386. X    #        be updated.
  1387. X
  1388. X    local ($faf);        # file name in cache
  1389. X    local ($time) = 0;        # timestamp
  1390. X
  1391. X    print STDOUT ("FTP Command execution:\n",
  1392. X          "    GET $file\n");
  1393. X
  1394. X    unless ( -d $ftp_cache && -w _ ) {
  1395. X    # No cache....
  1396. X    $faf = &fttemp;
  1397. X    }
  1398. X    else {
  1399. X
  1400. X    local ($rf, $rf_size, $rf_mtime) = &get_file_and_date ($file);
  1401. X
  1402. X    # Got it?
  1403. X    if ( $rf eq '' ) {
  1404. X        # No info, cannot use cache.
  1405. X        $faf = &fttemp;
  1406. X    }
  1407. X    else {
  1408. X        local ($af, $af_mtime, $tdiff);
  1409. X
  1410. X        # Look it up in the local ftp cache.
  1411. X        $af = &ftp_archname ($ftphost, $rf);
  1412. X        $faf = $ftp_cache . '/' . $af;
  1413. X
  1414. X        # Check size and timestamp.
  1415. X        if ( $rf_size == ( -s $faf ) ) {
  1416. X        $af_mtime = (stat(_))[9];
  1417. X        $tdiff = $af_mtime - $rf_mtime;
  1418. X        # Allow one hour difference (daylight savings).
  1419. X        if ( $tdiff == 0 || $tdiff == 3600 || $tdiff == -3600 ) {
  1420. X            # We have a valid file in the cache, return it.
  1421. X            print STDOUT "    [File found in local FTP cache]\n";
  1422. X            return $faf;
  1423. X        }
  1424. X        }
  1425. X
  1426. X        # Note the timestamp.
  1427. X        $time = $rf_mtime;
  1428. X
  1429. X        # Prepare to copy the file into the cache.
  1430. X        local ($tmp, @tmp);
  1431. X        $tmp = $ftp_cache;
  1432. X        @tmp = split (/\/+/, $af);
  1433. X        pop (@tmp);
  1434. X        foreach $dir ( @tmp ) {
  1435. X        $tmp .= '/' . $dir;
  1436. X        next if -d $tmp;
  1437. X        print STDOUT ("=> creating dir $tmp\n") if $opt_debug;
  1438. X        mkdir ($tmp, 0755) || print STDOUT ("    [mkdir $tmp: $!]\n");
  1439. X        }
  1440. X
  1441. X        if ( -d $tmp && -w $tmp ) {
  1442. X        unlink ($faf);
  1443. X        }
  1444. X        else {
  1445. X        local ($msg) = "No ftp cache for $af";
  1446. X        print STDOUT ("    [$msg]\n\n");
  1447. X        &writelog ("F $msg");
  1448. X        $faf = &fttemp;
  1449. X        }
  1450. X    }
  1451. X    }
  1452. X
  1453. X    # Fetch...
  1454. X    &ftp_type ('I');
  1455. X    if ( &ftp'get ($file, $faf, 0) ) {    #'){
  1456. X    # Set times to match the server.
  1457. X    utime (time, $time, $faf) if $time;
  1458. X    }
  1459. X
  1460. X    # Return the full name of the file.
  1461. X    $faf;
  1462. X}
  1463. X
  1464. Xsub ftp_dir {
  1465. X    local ($dir, $thefile) = @_;
  1466. X
  1467. X    local ($ret, *F);
  1468. X    open (F, '>' . $thefile);
  1469. X    print STDOUT ("FTP Command execution:\n",
  1470. X          "    DIR $dir\n");
  1471. X    &ftp_type ('A');
  1472. X    &ftp'dir_open ($dir);            #';
  1473. X    while ( $ret = &ftp'read ) {        #'){
  1474. X    $ftp'buf =~ s/\r\n/\n/g;        #';
  1475. X    print F $ftp'buf;            #';
  1476. X    }
  1477. X    &ftp'dir_close;                #';
  1478. X    close (F);
  1479. X}
  1480. X
  1481. Xsub ftp_type {
  1482. X    local ($type) = @_;
  1483. X    $current_ftp_type = '' unless defined $current_ftp_type;
  1484. X    unless ( $current_ftp_type eq $type ) {
  1485. X    &ftp'type ($type);        #';
  1486. X    $current_ftp_type = $type;
  1487. X    }
  1488. X}
  1489. X
  1490. Xsub get_file_and_date {
  1491. X    local ($file) = @_;        # returns (remote file name, size, date)
  1492. X
  1493. X    print STDOUT ("=> get_file_and_date ($file)\n") if $opt_debug;
  1494. X
  1495. X    local (@res, $result);
  1496. X
  1497. X    # Retrieve ls info from FTP server.
  1498. X    &ftp_type ('A');
  1499. X    &ftp'dir_open ($file);        #';
  1500. X    if ( $ret = &ftp'read ) {        #'){
  1501. X    ($result = $ftp'buf) =~ s/\r\n/\n/g;        #');
  1502. X    }
  1503. X    &ftp'dir_close;        #';
  1504. X    $result = $' if $result =~ /^total.*\n/i;
  1505. X    $result = $1 if $result =~ /^(.+)\n/i;
  1506. X    print STDOUT ("    ", $result, "\n");
  1507. X    # &ftp'type ('I');        #';
  1508. X    print STDOUT ("\n");
  1509. X
  1510. X    # Only the last few fields are relevant.
  1511. X    @res = split (' ', $result);
  1512. X
  1513. X    # Check for symlink.
  1514. X    if ( $res[$#res-1] eq '->' ) {
  1515. X    return ('', 0, 0)
  1516. X        unless $file = &resolve_symlink ($res[$#res-2], $res[$#res]);
  1517. X    return (&get_file_and_date ($file));
  1518. X    }
  1519. X
  1520. X    local ($size, $mon, $day, $year, $fn) = splice(@res,$#res-4, 5);
  1521. X    print STDOUT ("=> file = $file, size  = $size, Y/M/D = $year/$mon/$day\n")
  1522. X    if $opt_debug;
  1523. X
  1524. X    # Got it?
  1525. X    return ('', 0, 0) if $fn ne $file;
  1526. X
  1527. X    # Convert and return date.
  1528. X    require 'dateconv.pl';
  1529. X    return ($file, $size, &lstime_to_time ("$mon $day $year"));
  1530. X}
  1531. X
  1532. Xsub resolve_symlink {
  1533. X    local ($file, $link) = @_;
  1534. X
  1535. X    # This routine does a reasonable job on resolving symlinks.
  1536. X    # Since the symlinks we'll be resolving point to files on a
  1537. X    # remote system, we can hardly do better than this.
  1538. X
  1539. X    return $file unless $link;        # not a symlink
  1540. X
  1541. X    print STDOUT ("=> resolve_symlink ($file, $link)\n") if $opt_debug;
  1542. X
  1543. X    return $link if $link =~ m|^/|;    # absolute path
  1544. X    return undef if $link =~ m|^~|;    # cannot resolve
  1545. X
  1546. X    local (@file) = split (m|/+|, $file);
  1547. X    local (@link) = split (m|/+|, $link);
  1548. X    local ($result, $t) = ('','');
  1549. X    local ($skip) = 0;            # updir (..) skip count
  1550. X
  1551. X    pop (@file) if @file > 0;        # remove final component
  1552. X    push (@file, @link);        # add symlink value
  1553. X
  1554. X    # Normalize filename.
  1555. X    while ( @file ) {
  1556. X    $t = pop (@file);
  1557. X    next if $t eq '.';        # ignore
  1558. X    $skip++, next if $t eq '..';    # skip this and predecessor
  1559. X    $skip--, next if $skip;        # skip this
  1560. X    $result = $t . '/' . $result;    # prepend to result
  1561. X    }
  1562. X    chop ($result);        # chop trailing slash
  1563. X
  1564. X    print STDOUT ("=> resolved: $result\n") if $opt_debug;
  1565. X    $result;
  1566. X}
  1567. X
  1568. X1;
  1569. END_OF_FILE
  1570.   if test 5633 -ne `wc -c <'mserv-3.1/pr_ftp.pl'`; then
  1571.     echo shar: \"'mserv-3.1/pr_ftp.pl'\" unpacked with wrong size!
  1572.   fi
  1573.   # end of 'mserv-3.1/pr_ftp.pl'
  1574. fi
  1575. if test -f 'mserv-3.1/pr_help.pl' -a "${1}" != "-c" ; then 
  1576.   echo shar: Will not clobber existing file \"'mserv-3.1/pr_help.pl'\"
  1577. else
  1578.   echo shar: Extracting \"'mserv-3.1/pr_help.pl'\" \(6030 characters\)
  1579.   sed "s/^X//" >'mserv-3.1/pr_help.pl' <<'END_OF_FILE'
  1580. X# pr_help.pl -- auto-configuring HELP message
  1581. X# SCCS Status     : @(#)@ pr_help.pl    1.6
  1582. X# Author          : Johan Vromans
  1583. X# Created On      : Sun Dec 13 21:29:38 1992
  1584. X# Last Modified By: Johan Vromans
  1585. X# Last Modified On: Sat Jan  2 15:01:57 1993
  1586. X# Update Count    : 54
  1587. X# Status          : OK
  1588. X
  1589. X# Auto-configuring help message.
  1590. X#
  1591. X# The help texts are contained in array @help_msgs (standard commands)
  1592. X# and @ext_help (extended commands). The format for both arrays is the
  1593. X# same:
  1594. X# 
  1595. X#   +COMMAND NAME
  1596. X#   text line
  1597. X#   text line
  1598. X#   ...
  1599. X#   +COMMAND NAME
  1600. X#   text line
  1601. X#   ...
  1602. X# 
  1603. X# A lone '+' causes an blank line to be written.
  1604. X#
  1605. X# User extensions should call &add_help to add help texts to the help
  1606. X# system. 
  1607. X
  1608. Xsub do_help {
  1609. X
  1610. X    local ($line, $cmd) = '';
  1611. X
  1612. X    &setup_help unless defined @help_msgs;
  1613. X
  1614. X    select (STDOUT);
  1615. X    $~ = HELP_LINE;
  1616. X
  1617. X    print STDOUT ('Valid server commands are:', "\n\n");
  1618. X
  1619. X    unshift (@help_msgs,
  1620. X         '+BEGIN',
  1621. X         'Discard anything above this line, and start processing commands.',
  1622. X         '+HELP',
  1623. X         'This message.',
  1624. X         "\n",
  1625. X         'Use "send HELP" for a more detailed description on',
  1626. X         'how to use the mail server.');
  1627. X
  1628. X    push (@ext_help,
  1629. X      '+END',
  1630. X      'Terminate command processing.',
  1631. X      'The remainder of the input will be ignored.',
  1632. X      '+',
  1633. X      '+Case is not significant in the command verbs, '.
  1634. X      'but it *IS* significant',
  1635. X      '+in <path> and <item> specifications.');
  1636. X    push (@ext_help,
  1637. X      '+',
  1638. X      '+Mail messages originating from the any of the following accounts',
  1639. X      '+will be discarded (without notice)'.
  1640. X      ($black_list_warning ? ' in the future:' : ':'),
  1641. X      @black_list
  1642. X      ) if defined @black_list;
  1643. X
  1644. X    foreach ( @help_msgs, @ext_help, '+', '+' ) {
  1645. X    if ( /^\+/ ) {
  1646. X        if ( $cmd ne '' || $line =~ /[^ ]/ ) {
  1647. X        $= = 999;
  1648. X        foreach $text ( split (/\n/, $line) ) {
  1649. X            $text = $' if $text =~ /^ +/;
  1650. X            $text =~ s/ +/ /g;
  1651. X            write;
  1652. X            $cmd = '';
  1653. X        }
  1654. X        }
  1655. X        else {
  1656. X        print STDOUT "\n";
  1657. X        }
  1658. X        $cmd = $';
  1659. X        $line = ' ';
  1660. X    }
  1661. X    else {
  1662. X        $line .= $_ . ' ';
  1663. X    }
  1664. X    }
  1665. X
  1666. X
  1667. X    $didhelp = 1;
  1668. X}
  1669. X
  1670. Xsub setup_help {
  1671. X    local ($tmp);
  1672. X    local ($o_host) = $ftp ? '[<host>:]' : '';
  1673. X
  1674. X    push (@help_msgs,
  1675. X      '+REPLY <address>',
  1676. X      'Specify return address for replies.',
  1677. X      'Use this if you are not sure that',
  1678. X      'your mail system generates correct return addresses.');
  1679. X
  1680. X    push (@help_msgs,
  1681. X      '+MAIL <address>',
  1682. X      'Requests will be sent via email to <address>.');
  1683. X    push (@help_msgs,
  1684. X      'This is the default.')
  1685. X    if (defined $email && defined $uucp && !$prefer_uucp);
  1686. X
  1687. X    push (@help_msgs,
  1688. X      '+UUCP <host>!<path> <user>',
  1689. X      'Requests will be sent via uucp to <host>!<path>.',
  1690. X      'The <user> on <host> will be notified.',
  1691. X      '<path> must be writable by the UUCP system on <host>.')
  1692. X    if $uucp;
  1693. X    push (@help_msgs,
  1694. X      "\n",
  1695. X      'A UUCP command *MUST* be issued before any requests.')
  1696. X    if $uucp && !defined $email;
  1697. X
  1698. X    $tmp = '';
  1699. X    $tmp .= "$email_limits[1]K bytes for email" if defined $email;
  1700. X    $tmp .= ' and ' if defined $email && defined $uucp;
  1701. X    $tmp .= "$uucp_limits[1]K bytes for UUCP" if defined $uucp;
  1702. X    push (@help_msgs,
  1703. X      '+LIMIT <number>',
  1704. X      'Maximum number of Kbytes to be sent per transfer.',
  1705. X      "Default is $tmp.\n",
  1706. X      'The limit applies to subsequent "send" commands.');
  1707. X
  1708. X    $tmp = '[ENCODING] {';
  1709. X    $tmp .= ' BTOA |'        if -x $btoa;
  1710. X    $tmp .= ' UUE |'        if -x $uue;
  1711. X    $tmp .= ' XXENCODE |'    if -x $xxencode;
  1712. X    $tmp .= ' UUENCODE }';
  1713. X    push (@help_msgs,
  1714. X      "+$tmp",
  1715. X      'Specify encoding to be used.',
  1716. X      'Default is UUENCODE.',
  1717. X      'The encoding applies to subsequent "send" commands.');
  1718. X
  1719. X    push (@help_msgs,
  1720. X      '+CWD [<path>]',
  1721. X      'Sets or cancels the current working directory',
  1722. X      'for subsequent commands.');
  1723. X
  1724. X    push (@help_msgs,
  1725. X      "+DIR $o_host[<path>]",
  1726. X      'Returns a list of files in <path>.');
  1727. X    push (@help_msgs,
  1728. X      "\n", 'If a hostname is specified, retrieve the info',
  1729. X      'from <host> using anonymous FTP.')
  1730. X    if $ftp;
  1731. X
  1732. X    push (@help_msgs,
  1733. X      '+INDEX [<item>...]',
  1734. X      'Look up everything in the archives that matches the <item>s.',
  1735. X      'If no <item>s are specified, requests for a file named "INDEX".')
  1736. X    if defined $indexfile;
  1737. X
  1738. X    push (@help_msgs,
  1739. X      '+SEARCH <item> [<item>...]',
  1740. X      'Look up the indicated archive entries, and return a list of',
  1741. X      'files found.');
  1742. X
  1743. X    push (@help_msgs,
  1744. X      "+SEND $o_host<item> [<item>...]",
  1745. X      'Specify the items to be sent.');
  1746. X    push (@help_msgs,
  1747. X      "\n", 'If a hostname is specified, retrieve the files',
  1748. X      'from <host> using anonymous FTP.')
  1749. X    if $ftp;
  1750. X
  1751. X    push (@help_msgs,
  1752. X      "+RESEND $o_host<item> <part> [<part>...]",
  1753. X      'Re-sends the indicated <parts> from the specified <item>.',
  1754. X      'The encoding and limit must be identical to those used in the',
  1755. X      'original request.');
  1756. X    push (@help_msgs,
  1757. X      "\n", 'If a hostname is specified, retrieve the files',
  1758. X      'from <host> using anonymous FTP.')
  1759. X    if $ftp;
  1760. X
  1761. X    push (@help_msgs,
  1762. X      '+FTP USER <user> <password>',
  1763. X      'Set login information for subsequent FTP commands.',
  1764. X      '+FTP OPEN <host>',
  1765. X      'Open FTP connection to the indicated <host>.',
  1766. X      'If no login information was supplied, use anonymous FTP.',
  1767. X      "\n",
  1768. X      'If an FTP connection is open, subsequent commands',
  1769. X      '(SEND, RESEND, DIR, CWD) will be executed on <host>.',
  1770. X      '+FTP CLOSE',
  1771. X      'Close any open FTP connection.')
  1772. X    if $ftp;
  1773. X
  1774. X    push (@help_msgs,
  1775. X      '+ARCHIE PROG <request>',
  1776. X      'Consult Archie for <request> (a regular expression pattern).')
  1777. X    if $archie;
  1778. X
  1779. X    if ( defined $packing_limit ) {
  1780. X    $tmp = 'PACK {';
  1781. X    $tmp .= ' TAR |' if -x $tar || -x $pdtar;
  1782. X    $tmp .= ' ZOO |' if -x $zoo;
  1783. X    $tmp .= ' ZIP |' if -x $zip;
  1784. X    $tmp .= ' OFF }';
  1785. X    push (@help_msgs,
  1786. X          "+$tmp",
  1787. X          'Subsequent requests must specify directories,',
  1788. X          'which will be packed using the indicated method',
  1789. X          'and transferred.',
  1790. X          "\n", 'PACK OFF cancels packing.');
  1791. X    }
  1792. X}
  1793. X
  1794. Xformat HELP_LINE =
  1795. X@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~
  1796. X$cmd
  1797. X~~  ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1798. X$text
  1799. X.
  1800. X
  1801. X1;
  1802. END_OF_FILE
  1803.   if test 6030 -ne `wc -c <'mserv-3.1/pr_help.pl'`; then
  1804.     echo shar: \"'mserv-3.1/pr_help.pl'\" unpacked with wrong size!
  1805.   fi
  1806.   # end of 'mserv-3.1/pr_help.pl'
  1807. fi
  1808. if test -f 'mserv-3.1/report.pl' -a "${1}" != "-c" ; then 
  1809.   echo shar: Will not clobber existing file \"'mserv-3.1/report.pl'\"
  1810. else
  1811.   echo shar: Extracting \"'mserv-3.1/report.pl'\" \(7200 characters\)
  1812.   sed "s/^X//" >'mserv-3.1/report.pl' <<'END_OF_FILE'
  1813. X#!/usr/local/bin/perl
  1814. X# report.pl -- make mail server report
  1815. X# SCCS Status     : @(#)@ report    3.14
  1816. X# Author          : Johan Vromans
  1817. X# Created On      : Sat May  2 14:23:10 1992
  1818. X# Last Modified By: Johan Vromans
  1819. X# Last Modified On: Fri Dec 25 16:22:32 1992
  1820. X# Update Count    : 67
  1821. X# Status          : Unknown, Use with caution!
  1822. X
  1823. X# Read the mail server logfile, and create a report.
  1824. X
  1825. X$my_name = "report";
  1826. X$my_version = "3.14";
  1827. X#
  1828. X################ Common stuff ################
  1829. X
  1830. X$libdir = $ENV{"MSERVLIB"} || "/usr/local/lib/mserv";
  1831. Xunshift (@INC, $libdir);
  1832. X
  1833. X################ Options handling ################
  1834. X
  1835. X&options if @ARGV > 0 && $ARGV[0] =~ /^-+[^-]+/;
  1836. Xrequire "ms_common.pl";
  1837. X$opt_usage = 1 unless $opt_errors;
  1838. X@ARGV = ( $logfile ) unless @ARGV > 0;
  1839. X$now = time;
  1840. X
  1841. X################ Preamble ################
  1842. X
  1843. Xrequire "$libdir/rfc822.pl";
  1844. X
  1845. Xformat std_hdr =
  1846. XMail Server Report for @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<     @>>>>>>>>>>>>
  1847. X"$thismonth 19$year -- by $report_type", "Page $%"
  1848. X
  1849. X                                                         1111111111222222222233
  1850. X@<<<<<<<<<<<<<<<<<<<                 Type Total 1234567890123456789012345678901
  1851. X$report_type
  1852. X-------------------------------------------------------------------------------
  1853. X.
  1854. X
  1855. Xformat std_out =
  1856. X^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @ @>>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  1857. X$item, $type, $count, $seq
  1858. X ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
  1859. X$item
  1860. X.
  1861. X
  1862. X################ Main ################
  1863. X
  1864. X$logfile = $ARGV[0] if @ARGV == 1;
  1865. X
  1866. Xopen (LOG, $logfile) || die ("$my_name: Cannot open $logfile [$!]\n");
  1867. X
  1868. X$curmonth = "";
  1869. X@mnames = split (/,/, "January,February,March,April,May,June," .
  1870. X        "July,August,September,October,November,December");
  1871. X
  1872. X# Form pattern for the known libraries so we can easily
  1873. X# strip them off the names of the requests.
  1874. X$libpat = "(";
  1875. Xforeach $lib ( @libdirs ) {
  1876. X    $lib =~ s/(\W)/\\\1/g;
  1877. X    $libpat .= $lib . "|";
  1878. X}
  1879. Xchop ($libpat);
  1880. X$libpat .= ")";
  1881. X
  1882. X# Process logfile.
  1883. X$msgcnt = 0;
  1884. Xwhile ( <LOG> ) {
  1885. X
  1886. X    # 891002 19:48 M "Neil Dixon <neil@yc1>" /u2/goodies/gwm/INDEX U1/1 32678
  1887. X    #    0     1   2             3                  4                5    6
  1888. X
  1889. X    # Note: $size is not used (yet).
  1890. X    ($date, $time, $type, $user, $pkg, $part, $size) = 
  1891. X    /^(\S+)\s+(\S+)\s(\S+)\s+"([^\042]+)"\s+(.+)\s+(\S+\/\d+)\s+(\S+)$/;
  1892. X
  1893. X    unless ( defined $user ) {    # Assume error record.
  1894. X
  1895. X    next unless $opt_errors;
  1896. X
  1897. X    ($date, $time, $msg) = 
  1898. X        /^(\S+)\s+(\S+)\s+(.+)$/;
  1899. X    $date .= " " . $time;
  1900. X    next if $since && $date lt $since; 
  1901. X
  1902. X    if ( $msgcnt == 0 && $since ) {
  1903. X        print STDERR ("Errors since $since\n\n");
  1904. X    }
  1905. X    print STDERR ($date, " ", $msg, "\n");
  1906. X    $msgcnt++;
  1907. X    next;
  1908. X    }
  1909. X
  1910. X    next unless $opt_usage;
  1911. X
  1912. X    # Use first parts for accounting only.
  1913. X    next unless $part =~ m|^[^0-9]*1/|;
  1914. X
  1915. X    # Get date.
  1916. X    $year = substr ($date, 0, 2);
  1917. X    $month = substr ($date, 2, 2);
  1918. X    $day = substr ($date, 4, 2);
  1919. X
  1920. X    # Strip known libraries.
  1921. X    $pkg = $' if $pkg =~ /^$libpat\//o;
  1922. X    $pkg = $` if $pkg =~ /\s+\(.+\)$/;
  1923. X    $pkg .= $type;
  1924. X
  1925. X    # Generate a new report page if the month runs over.
  1926. X    if ( $curmonth ne $month ) {
  1927. X    if ( $curmonth ne "" ) {
  1928. X        &report;
  1929. X        $- = 0;            # Force page break.
  1930. X        reset "Z";
  1931. X    }
  1932. X    $curmonth = $month;
  1933. X    $thismonth = $mnames[$curmonth-1];
  1934. X    $weeksh = &firstday ($month, $year);
  1935. X    }
  1936. X
  1937. X    # Normalize addresses and count them.
  1938. X    &rfc822'parse_addresses ($user);
  1939. X    $user = $rfc822'addresses[0] . $type;
  1940. X    $Zucounts{$user}++;
  1941. X    $Zudays{$user} |= 1 << ($day - 1);
  1942. X    $Zpcounts{$pkg}++;
  1943. X    $Zpdays{$pkg} |= 1 << ($day - 1);
  1944. X}
  1945. Xclose (LOG);
  1946. X
  1947. X# Update since-file.
  1948. Xif ( $opt_since && !$opt_noupdate ) {
  1949. X    utime ($now, $now, $opt_since) ||
  1950. X    print STDERR ("Cannot change times on \"$opt_since\" [$!]\n");
  1951. X}
  1952. X
  1953. X# Now for the remaining usage reports ...
  1954. X&report if $opt_usage;
  1955. X
  1956. X# That's it ...
  1957. Xexit (0);
  1958. X
  1959. X################ Subroutines ################
  1960. X
  1961. Xsub report {
  1962. X    $^ = "std_hdr";
  1963. X    $~ = "std_out";
  1964. X    $: = " \n-/";
  1965. X    &report1;
  1966. X    print STDOUT ($^L);        # Form-feed between reports.
  1967. X    &report2;
  1968. X}
  1969. X
  1970. Xsub report1 {
  1971. X    local ($report_type) = "User";
  1972. X    local ($total) = 0;
  1973. X    local ($days) = 0;
  1974. X    local ($seq, $days, $count, $type);
  1975. X    $- = 0;
  1976. X    $% = 0;
  1977. X
  1978. X    foreach $item (sort (keys (%Zucounts))) {
  1979. X    $seq = &daylist ($Zudays{$item});
  1980. X    $days |= $Zpdays{$item};
  1981. X    $count = $Zucounts{$item};
  1982. X    $total += $count;
  1983. X    $type = chop ($item);
  1984. X    write;
  1985. X    }
  1986. X    $item = "TOTAL";
  1987. X    $type = "";
  1988. X    $seq = &daylist ($days);
  1989. X    $count = $total;
  1990. X    write;
  1991. X}
  1992. X
  1993. Xsub report2 {
  1994. X    local ($report_type) = "Package";
  1995. X    local ($total) = 0;
  1996. X    local ($days) = 0;
  1997. X    local ($seq, $days, $count, $type);
  1998. X    $- = 0;
  1999. X    $% = 0;
  2000. X
  2001. X    foreach $item (sort (keys (%Zpcounts))) {
  2002. X    $seq = &daylist ($Zpdays{$item});
  2003. X    $days |= $Zpdays{$item};
  2004. X    $count = $Zpcounts{$item};
  2005. X    $total += $count;
  2006. X    $type = chop ($item);
  2007. X    write;
  2008. X    }
  2009. X    $item = "TOTAL";
  2010. X    $type = "";
  2011. X    $seq = &daylist ($days);
  2012. X    $count = $total;
  2013. X    write;
  2014. X}
  2015. X
  2016. Xsub daylist {
  2017. X    local ($day) = pop (@_);
  2018. X    local ($seq) = "";
  2019. X    local ($cc) = 1;
  2020. X
  2021. X    while ( $cc <= 31 ) {
  2022. X    if ( $day & 0x1 ) {
  2023. X        $seq .= substr ("SMTWTFS", ($cc - $weeksh + 7) % 7, 1);
  2024. X    }
  2025. X    else {
  2026. X        $seq = "$seq ";
  2027. X    }
  2028. X    $day >>= 1;
  2029. X    $cc++;
  2030. X    }
  2031. X    return $seq;
  2032. X}
  2033. X
  2034. Xsub firstday {
  2035. X    local ($month) = shift (@_);
  2036. X    local ($year) = shift (@_);
  2037. X    local ($t);
  2038. X    local (@tm); 
  2039. X
  2040. X    $t = 
  2041. X    ($year - 70) * (365 * 24 * 60 * 60) +
  2042. X        ($month - 1) * (28 * 24 * 60 * 60);
  2043. X    $month--;
  2044. X
  2045. X    do {
  2046. X    @tm = localtime ($t);
  2047. X    $t += (28 * 24 * 60 * 60);
  2048. X    }
  2049. X    while (($tm[5] < $year) || ($tm[4] < $month));
  2050. X
  2051. X    $t = ($tm[3] - $tm[6]) % 7;
  2052. X    $t += 7 if $t < 0;
  2053. X    return $t;
  2054. X}
  2055. X
  2056. Xsub options {
  2057. X    local ($opt_full, $opt_help, $opt_ident) = (0, 0, 0);
  2058. X
  2059. X    require "newgetopt.pl";
  2060. X
  2061. X    $opt_errors = $opt_usage = 0;
  2062. X    if ( !&NGetOpt ("config=s", "ident", "errors", "usage", "full",
  2063. X            "since=s", "noupdate",
  2064. X            "help")
  2065. X    || $opt_help
  2066. X    || (@ARGV > 1)) {
  2067. X    &usage;
  2068. X    }
  2069. X    $opt_errors |= $opt_full;
  2070. X    $opt_usage |= $opt_full;
  2071. X    print ($my_package, " [", $my_name, " ", $my_version, "]\n")
  2072. X    if $opt_ident && $opt_usage;
  2073. X    print STDERR ($my_package, " [", $my_name, " ", $my_version, "]\n")
  2074. X    if $opt_ident && $opt_errors;
  2075. X    if ( defined $opt_since ) {
  2076. X    local ($a) = (stat ($opt_since))[9];
  2077. X    die ("Cannot timestamp \"$opt_since\" [$!]\n") unless $a > 0;
  2078. X    local (@tm) = localtime ($a);
  2079. X    $since = sprintf ("%02d%02d%02d %02d:%02d",
  2080. X              $tm[5], 1+$tm[4], $tm[3], $tm[2], $tm[1]);
  2081. X    $opt_noupdate = defined $opt_noupdate;
  2082. X    }
  2083. X    else {
  2084. X    $since = "";
  2085. X    }
  2086. X    $config_file = $opt_config if defined $opt_config;
  2087. X}
  2088. X
  2089. Xsub usage {
  2090. X    require "ms_common.pl";
  2091. X    print STDERR <<EndOfUsage;
  2092. X$my_package [$my_name $my_version]
  2093. X
  2094. XUsage: $my_name [options] [ logfile ]
  2095. X
  2096. XOptions:
  2097. X    -config XX    use alternate config file
  2098. X    -errors    generate error report to STDERR
  2099. X    -usage    generate usage report to STDOUT
  2100. X    -full    generate usage report and error report
  2101. X    -since FILE    only error messages newer than FILE
  2102. X        (FILE date will be updated upon successful completion)
  2103. X    -noupdate    do not update FILE
  2104. X    -help    this message
  2105. X    -ident    print program identification
  2106. X
  2107. XDefault action is to generate a usage report from logfile
  2108. X"$logfile".
  2109. XEndOfUsage
  2110. X    exit (1);
  2111. X}
  2112. END_OF_FILE
  2113.   if test 7200 -ne `wc -c <'mserv-3.1/report.pl'`; then
  2114.     echo shar: \"'mserv-3.1/report.pl'\" unpacked with wrong size!
  2115.   fi
  2116.   # end of 'mserv-3.1/report.pl'
  2117. fi
  2118. if test -f 'mserv-3.1/ud_sample1.pl' -a "${1}" != "-c" ; then 
  2119.   echo shar: Will not clobber existing file \"'mserv-3.1/ud_sample1.pl'\"
  2120. else
  2121.   echo shar: Extracting \"'mserv-3.1/ud_sample1.pl'\" \(1583 characters\)
  2122.   sed "s/^X//" >'mserv-3.1/ud_sample1.pl' <<'END_OF_FILE'
  2123. X# userdefs.pl -- sample userdefs.
  2124. X# SCCS Status     : @(#)@ ud_sample1.pl    1.3
  2125. X# Author          : Johan Vromans
  2126. X# Created On      : Fri Dec 18 22:29:57 1992
  2127. X# Last Modified By: Johan Vromans
  2128. X# Last Modified On: Fri Jan  1 18:01:30 1993
  2129. X# Update Count    : 19
  2130. X# Status          : Use at your own risk
  2131. X
  2132. X# How to implement Mail Server extensions.
  2133. X#
  2134. X#  1. Write a subroutine to parse the command.
  2135. X#     See 'pr_parse.pl' for lots of examples.
  2136. X#     Any work should be pushed on the @workq.
  2137. X#  2. Add a command verb to $cmd_tbl, pointing to this routine.
  2138. X#     The command verb must be in ALL UPPERCASE.
  2139. X#  3. Write a subroutine to execute the command.
  2140. X#     See 'pr_dowork.pl' for lots of examples.
  2141. X#  4. Add a command verb to $exe_tbl, pointing to this routine.
  2142. X#     Since the Mail Server uses uppercase command verbs, 
  2143. X#     please use a lowercase verb.
  2144. X#  5. Add a help message using &add_help.
  2145. X#
  2146. X# As an example, the following code adds the 'REPORT' command to the
  2147. X# Mail Server.
  2148. X
  2149. Xsub cmd_report {            # step 1.
  2150. X    # Check syntax.
  2151. X    # $cmd is the command verb, upcased.
  2152. X    # @cmd has the remainder of the command.
  2153. X    return &errmsg ("Usage: $cmd") unless @cmd == 0;
  2154. X
  2155. X    # Push exe command on work queue.
  2156. X    push (@workq, &zp ('r'));
  2157. X
  2158. X    # Feedback.
  2159. X    print STDOUT ("=> Okay\n");
  2160. X    1;
  2161. X}
  2162. X
  2163. X$cmd_tbl{'REPORT'} = 'cmd_report';    # step 2.
  2164. X
  2165. Xsub exe_report {            # step 3.
  2166. X    &do_unix ("$libdir/report -usage");
  2167. X    1;
  2168. X}
  2169. X
  2170. X$exe_tbl{'r'} = 'exe_report';        # step 4.
  2171. X
  2172. X&add_help ('REPORT',            # step 5.
  2173. X       'Generate a mail server usage report.');
  2174. X
  2175. X################ 1 ################
  2176. X1;
  2177. END_OF_FILE
  2178.   if test 1583 -ne `wc -c <'mserv-3.1/ud_sample1.pl'`; then
  2179.     echo shar: \"'mserv-3.1/ud_sample1.pl'\" unpacked with wrong size!
  2180.   fi
  2181.   # end of 'mserv-3.1/ud_sample1.pl'
  2182. fi
  2183. echo shar: End of archive 5 \(of 6\).
  2184. cp /dev/null ark5isdone
  2185. MISSING=""
  2186. for I in 1 2 3 4 5 6 ; do
  2187.     if test ! -f ark${I}isdone ; then
  2188.     MISSING="${MISSING} ${I}"
  2189.     fi
  2190. done
  2191. if test "${MISSING}" = "" ; then
  2192.     echo You have unpacked all 6 archives.
  2193.     rm -f ark[1-9]isdone
  2194. else
  2195.     echo You still must unpack the following archives:
  2196.     echo "        " ${MISSING}
  2197. fi
  2198. exit 0
  2199. exit 0 # Just in case...
  2200.