home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / sources / misc / 4238 < prev    next >
Encoding:
Text File  |  1993-01-06  |  59.4 KB  |  2,206 lines

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