home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume34 / mserv / part03 < prev    next >
Encoding:
Text File  |  1993-01-05  |  59.5 KB  |  2,275 lines

  1. Newsgroups: comp.sources.misc
  2. From: jv@squirrel.mh.nl (Johan Vromans)
  3. Subject: v34i094:  mserv - Squirrel Mail Server Software, version 3.1, Part03/06
  4. Message-ID: <1993Jan7.034829.11630@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4c172a367943ba39686e2f00b30a81e4
  6. Date: Thu, 7 Jan 1993 03:48:29 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jv@squirrel.mh.nl (Johan Vromans)
  10. Posting-number: Volume 34, Issue 94
  11. Archive-name: mserv/part03
  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/ftp.pl mserv-3.1/ms_config.pl
  20. #   mserv-3.1/mserv.notesi mserv-3.1/process.pl
  21. # Wrapped by kent@sparky on Wed Jan  6 21:39:46 1993
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 3 (of 6)."'
  25. if test -f 'mserv-3.1/ftp.pl' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'mserv-3.1/ftp.pl'\"
  27. else
  28.   echo shar: Extracting \"'mserv-3.1/ftp.pl'\" \(22946 characters\)
  29.   sed "s/^X//" >'mserv-3.1/ftp.pl' <<'END_OF_FILE'
  30. X# ftp.pl -- 
  31. X# SCCS Status     : @(#)@ ftp    1.3
  32. X# Last Modified By: Johan Vromans
  33. X# Last Modified On: Wed Dec 30 14:31:38 1992
  34. X# Update Count    : 3
  35. X# Status          : OK
  36. X
  37. X# This is a wrapper to the chat2.pl routines that make life easier
  38. X# to do ftp type work.
  39. X# Written by Alan R. Martello <al@ee.pitt.edu>
  40. X# Some bug fixes and extensions by Lee McLoughlin <lmjm@doc.ic.ac.uk>
  41. X# And by A.Macpherson@bnr.co.uk for multi-homed hosts
  42. X#
  43. X# Adopted for use by the Squirrel Mail Server Software by Johan Vromans <jv@mh.nl>.
  44. X# Only modification: indent all output with four spaces.
  45. X#             show password string if user is anonymous.
  46. X#
  47. X# $Header: /a/swan/home/swan/staff/csg/lmjm/src/perl/mirror/RCS/ftp.pl,v 1.13 1992/03/20 21:01:03 lmjm Exp lmjm $
  48. X# $Log: ftp.pl,v $
  49. X# Revision 1.13  1992/03/20  21:01:03  lmjm
  50. X# Added in the proxy ftp code from Edwards Reed <err@cinops.xerox.com>
  51. X# Added  ftp'delete from Aaron Wohl <aw0g+@andrew.cmu.edu>
  52. X#
  53. X# Revision 1.12  1992/02/06  23:25:56  lmjm
  54. X# Moved code around so can use this as a lib for both mirror and ftpmail.
  55. X# Time out opens.  In case Unix doesn't bother to.
  56. X#
  57. X# Revision 1.11  1991/11/27  22:05:57  lmjm
  58. X# Match the response code number at the start of a line allowing
  59. X# for any leading junk.
  60. X#
  61. X# Revision 1.10  1991/10/23  22:42:20  lmjm
  62. X# Added better timeout code.
  63. X# Tried to optimise file transfer
  64. X# Moved open/close code to not leak file handles.
  65. X# Cleaned up the alarm code.
  66. X# Added $fatalerror to show wether the ftp link is really dead.
  67. X#
  68. X# Revision 1.9  1991/10/07  18:30:35  lmjm
  69. X# Made the timeout-read code work.
  70. X# Added restarting file gets.
  71. X# Be more verbose if ever have to call die.
  72. X#
  73. X# Revision 1.8  1991/09/17  22:53:16  lmjm
  74. X# Spot when open_data_socket fails and return a failure rather than dying.
  75. X#
  76. X# Revision 1.7  1991/09/12  22:40:25  lmjm
  77. X# Added Andrew Macpherson's patches for hosts without ip forwarding.
  78. X#
  79. X# Revision 1.6  1991/09/06  19:53:52  lmjm
  80. X# Relaid out the code the way I like it!
  81. X# Changed the debuggin to produce more "appropriate" messages
  82. X# Fixed bugs in the ordering of put and dir listing.
  83. X# Allow for hash printing when getting files (a la ftp).
  84. X# Added the new commands from Al.
  85. X# Don't print passwords in debugging.
  86. X#
  87. X# Revision 1.5  1991/08/29  16:23:49  lmjm
  88. X# Timeout reads from the remote ftp server.
  89. X# No longer call die expect on fatal errors.  Just return fail codes.
  90. X# Changed returns so higher up routines can tell whats happening.
  91. X# Get expect/accept in correct order for dir listing.
  92. X# When ftp_show is set then print hashes every 1k transfered (like ftp).
  93. X# Allow for stripping returns out of incoming data.
  94. X# Save last error in a global string.
  95. X#
  96. X# Revision 1.4  1991/08/14  21:04:58  lmjm
  97. X# ftp'get now copes with ungetable files.
  98. X# ftp'expect code changed such that the string_to_print is
  99. X# ignored and the string sent back from the remote system is printed
  100. X# instead.
  101. X# Implemented patches from al.  Removed spuiours tracing statements.
  102. X#
  103. X# Revision 1.3  1991/08/09  21:32:18  lmjm
  104. X# Allow for another ok code on cwd's
  105. X# Rejigger the log levels
  106. X# Send \r\n for some odd ftp daemons
  107. X#
  108. X# Revision 1.2  1991/08/09  18:07:37  lmjm
  109. X# Don't print messages unless ftp_show says to.
  110. X#
  111. X# Revision 1.1  1991/08/08  20:31:00  lmjm
  112. X# Initial revision
  113. X#
  114. X
  115. Xrequire 'chat2.pl';
  116. Xrequire 'sys/socket.ph';
  117. X
  118. Xpackage ftp;
  119. X
  120. X# If the remote ftp daemon doesn't respond within this time presume its dead
  121. X# or something.
  122. X$timeout = 30;
  123. X
  124. X# Timeout a read if I don't get data back within this many seconds
  125. X$timeout_read = 20 * $timeout;
  126. X
  127. X# Timeout an open
  128. X$timeout_open = $timeout;
  129. X
  130. X# This is a "global" it contains the last response from the remote ftp server
  131. X# for use in error messages
  132. X$ftp'response = "";
  133. X# Also ftp'NS is the socket containing the data coming in from the remote ls
  134. X# command.
  135. X
  136. X# The size of block to be read or written when talking to the remote
  137. X# ftp server
  138. X$ftp'ftpbufsize = 4096;
  139. X
  140. X# How often to print a hash out, when debugging
  141. X$ftp'hashevery = 1024;
  142. X# Output a newline after this many hashes to prevent outputing very long lines
  143. X$ftp'hashnl = 70;
  144. X
  145. X# If a proxy connection then who am I really talking to?
  146. X$real_site = "";
  147. X
  148. X# This is just a tracing aid.
  149. X$ftp_show = 0;
  150. Xsub ftp'debug
  151. X{
  152. X    $ftp_show = @_[0];
  153. X#    if( $ftp_show ){
  154. X#        print "    ftp debugging on\n";
  155. X#    }
  156. X}
  157. X
  158. Xsub ftp'set_timeout
  159. X{
  160. X    $timeout = @_[0];
  161. X    $timeout_open = $timeout;
  162. X    $timeout_read = 20 * $timeout;
  163. X    if( $ftp_show ){
  164. X        print "    ftp timeout set to $timeout\n";
  165. X    }
  166. X}
  167. X
  168. X
  169. Xsub ftp'open_alarm
  170. X{
  171. X    die "timeout: open";
  172. X}
  173. X
  174. Xsub ftp'timed_open
  175. X{
  176. X    local( $site, $ftp_port, $retry_call, $attempts ) = @_;
  177. X    local( $connect_site, $connect_port );
  178. X    local( $res );
  179. X
  180. X    alarm( $timeout_open );
  181. X
  182. X    while( $attempts-- ){
  183. X        if( $ftp_show ){
  184. X            print "    proxy connecting via $proxy_gateway [$proxy_ftp_port]\n" if $proxy;
  185. X            print "    Connecting to $site";
  186. X            if( $ftp_port != 21 ){
  187. X                print " [port $ftp_port]";
  188. X            }
  189. X            print "\n";
  190. X        }
  191. X        
  192. X        if( $proxy ) {
  193. X            if( ! $proxy_gateway ) {
  194. X                # if not otherwise set
  195. X                $proxy_gateway = "internet-gateway";
  196. X            }
  197. X            if( $debug ) {
  198. X                print "    using proxy services of $proxy_gateway, ";
  199. X                print "at $proxy_ftp_port\n";
  200. X            }
  201. X            $connect_site = $proxy_gateway;
  202. X            $connect_port = $proxy_ftp_port;
  203. X            $real_site = $site;
  204. X        }
  205. X        else {
  206. X            $connect_site = $site;
  207. X            $connect_port = $ftp_port;
  208. X        }
  209. X        if( ! &chat'open_port( $connect_site, $connect_port ) ){
  210. X            if( $retry_call ){
  211. X                print "    Failed to connect\n" if $ftp_show;
  212. X                next;
  213. X            }
  214. X            else {
  215. X                print "    proxy connection failed " if $proxy;
  216. X                print "    Cannot open ftp to $connect_site\n" if $ftp_show;
  217. X                return 0;
  218. X            }
  219. X        }
  220. X        $res = &ftp'expect( $timeout,
  221. X                    120, "service unavailable to $site", 0, 
  222. X                                220, "ready for login to $site", 1,
  223. X                    421, "service unavailable to $site, closing connection", 0);
  224. X        if( ! $res ){
  225. X            &chat'close();
  226. X            next;
  227. X        }
  228. X        return 1;
  229. X    }
  230. X    continue {
  231. X        print "    Pausing between retries\n";
  232. X        sleep( $retry_pause );
  233. X    }
  234. X    return 0;
  235. X}
  236. X
  237. Xsub ftp'open
  238. X{
  239. X    local( $site, $ftp_port, $retry_call, $attempts ) = @_;
  240. X
  241. X    $SIG{ 'ALRM' } = "ftp\'open_alarm";
  242. X
  243. X    local( $ret ) = eval "&timed_open( '$site', $ftp_port, $retry_call, $attempts )";
  244. X    alarm( 0 );
  245. X
  246. X    if( $@ =~ /^timeout/ ){
  247. X        return -1;
  248. X    }
  249. X    return $ret;
  250. X}
  251. X
  252. Xsub ftp'login
  253. X{
  254. X    local( $remote_user, $remote_password ) = @_;
  255. X
  256. X    if( $proxy ){
  257. X        &ftp'send( "USER $remote_user@$site" );
  258. X    }
  259. X    else {
  260. X        &ftp'send( "USER $remote_user" );
  261. X    }
  262. X        local( $val ) =
  263. X               &ftp'expect($timeout,
  264. X               230, "$remote_user logged in", 1,
  265. X           331, "send password for $remote_user", 2,
  266. X
  267. X           500, "syntax error", 0,
  268. X           501, "syntax error", 0,
  269. X           530, "not logged in", 0,
  270. X           332, "account for login not supported", 0,
  271. X
  272. X           421, "service unavailable, closing connection", 0);
  273. X    if( $val == 1 ){
  274. X        return 1;
  275. X    }
  276. X    if( $val == 2 ){
  277. X        # A password is needed
  278. X        &ftp'send( "PASS $remote_password" );
  279. X
  280. X        $val = &ftp'expect( $timeout,
  281. X#           "[.|\n]*^230", "$remote_user logged in", 1,
  282. X           230, "$remote_user logged in", 1,
  283. X
  284. X           202, "command not implemented", 0,
  285. X           332, "account for login not supported", 0,
  286. X
  287. X           530, "not logged in", 0,
  288. X           500, "syntax error", 0,
  289. X           501, "syntax error", 0,
  290. X           503, "bad sequence of commands", 0, 
  291. X
  292. X           421, "service unavailable, closing connection", 0);
  293. X        if( $val == 1){
  294. X            # Logged in
  295. X            return 1;
  296. X        }
  297. X    }
  298. X    # If I got here I failed to login
  299. X    return 0;
  300. X}
  301. X
  302. Xsub ftp'close
  303. X{
  304. X    &ftp'quit();
  305. X    &chat'close();
  306. X}
  307. X
  308. X# Change directory
  309. X# return 1 if successful
  310. X# 0 on a failure
  311. Xsub ftp'cwd
  312. X{
  313. X    local( $dir ) = @_;
  314. X
  315. X    &ftp'send( "CWD $dir" );
  316. X
  317. X    return &ftp'expect( $timeout,
  318. X        200, "working directory = $dir", 1,
  319. X        250, "working directory = $dir", 1,
  320. X
  321. X        500, "syntax error", 0,
  322. X        501, "syntax error", 0,
  323. X                502, "command not implemented", 0,
  324. X        530, "not logged in", 0,
  325. X                550, "cannot change directory", 0,
  326. X        421, "service unavailable, closing connection", 0 );
  327. X}
  328. X
  329. X# Get a full directory listing:
  330. X# &ftp'dir( remote LIST options )
  331. X# Start a list goin with the given options.
  332. X# Presuming that the remote deamon uses the ls command to generate the
  333. X# data to send back then then you can send it some extra options (eg: -lRa)
  334. X# return 1 if sucessful and 0 on a failure
  335. Xsub ftp'dir_open
  336. X{
  337. X    local( $options ) = @_;
  338. X    local( $ret );
  339. X    
  340. X    if( ! &ftp'open_data_socket() ){
  341. X        return 0;
  342. X    }
  343. X    
  344. X    if( $options ){
  345. X        &ftp'send( "LIST $options" );
  346. X    }
  347. X    else {
  348. X        &ftp'send( "LIST" );
  349. X    }
  350. X    
  351. X    $ret = &ftp'expect( $timeout,
  352. X        150, "reading directory", 1,
  353. X    
  354. X        125, "data connection already open?", 0,
  355. X    
  356. X        450, "file unavailable", 0,
  357. X        500, "syntax error", 0,
  358. X        501, "syntax error", 0,
  359. X        502, "command not implemented", 0,
  360. X        530, "not logged in", 0,
  361. X    
  362. X           421, "service unavailable, closing connection", 0 );
  363. X    if( ! $ret ){
  364. X        &ftp'close_data_socket;
  365. X        return 0;
  366. X    }
  367. X    
  368. X    # 
  369. X    # the data should be coming at us now
  370. X    #
  371. X    
  372. X    # now accept
  373. X    accept(NS,S) || die "accept failed $!";
  374. X    
  375. X    return 1;
  376. X}
  377. X
  378. X
  379. X# Close down reading the result of a remote ls command
  380. X# return 1 if successful and 0 on failure
  381. Xsub ftp'dir_close
  382. X{
  383. X    local( $ret );
  384. X
  385. X    # read the close
  386. X    #
  387. X    $ret = &ftp'expect($timeout,
  388. X            226, "", 1,     # transfer complete, closing connection
  389. X            250, "", 1,     # action completed
  390. X
  391. X            425, "can't open data connection", 0,
  392. X            426, "connection closed, transfer aborted", 0,
  393. X            451, "action aborted, local error", 0,
  394. X            421, "service unavailable, closing connection", 0);
  395. X
  396. X    # shut down our end of the socket
  397. X    &ftp'close_data_socket;
  398. X
  399. X    if( ! $ret ){
  400. X        return 0;
  401. X    }
  402. X
  403. X    return 1;
  404. X}
  405. X
  406. X# Quit from the remote ftp server
  407. X# return 1 if successful and 0 on failure
  408. Xsub ftp'quit
  409. X{
  410. X    $site_command_check = 0;
  411. X    @site_command_list = ();
  412. X
  413. X    &ftp'send("QUIT");
  414. X
  415. X    return &ftp'expect($timeout, 
  416. X        221, "Goodbye", 1,     # transfer complete, closing connection
  417. X    
  418. X        500, "error quitting??", 0);
  419. X}
  420. X
  421. Xsub ftp'read_alarm
  422. X{
  423. X    die "timeout: read";
  424. X}
  425. X
  426. Xsub ftp'timed_read
  427. X{
  428. X    alarm( $timeout_read );
  429. X    return sysread( NS, $buf, $ftpbufsize );
  430. X}
  431. X
  432. Xsub ftp'read
  433. X{
  434. X    $SIG{ 'ALRM' } = "ftp\'read_alarm";
  435. X
  436. X    local( $ret ) = eval '&timed_read()';
  437. X    alarm( 0 );
  438. X
  439. X    if( $@ =~ /^timeout/ ){
  440. X        return -1;
  441. X    }
  442. X    return $ret;
  443. X}
  444. X
  445. X# Get a remote file back into a local file.
  446. X# If no loc_fname passed then uses rem_fname.
  447. X# returns 1 on success and 0 on failure
  448. Xsub ftp'get
  449. X{
  450. X    local($rem_fname, $loc_fname, $restart ) = @_;
  451. X    
  452. X    if ($loc_fname eq "") {
  453. X        $loc_fname = $rem_fname;
  454. X    }
  455. X    
  456. X    if( ! &ftp'open_data_socket() ){
  457. X        print "    Cannot open data socket\n";
  458. X        return 0;
  459. X    }
  460. X
  461. X    # Find the size of the target file
  462. X    local( $restart_at ) = &ftp'filesize( $loc_fname );
  463. X    if( $restart && $restart_at > 0 && &ftp'restart( $restart_at ) ){
  464. X        $restart = 1;
  465. X        # Make sure the file can be updated
  466. X        chmod( 0644, $loc_fname );
  467. X    }
  468. X    else {
  469. X        $restart = 0;
  470. X        unlink( $loc_fname );
  471. X    }
  472. X
  473. X    &ftp'send( "RETR $rem_fname" );
  474. X    
  475. X    local( $ret ) =
  476. X        &ftp'expect($timeout, 
  477. X                   150, "receiving $loc_fname", 1,
  478. X
  479. X                   125, "data connection already open?", 0,
  480. X
  481. X                   450, "file unavailable", 2,
  482. X                   550, "file unavailable", 2,
  483. X
  484. X           500, "syntax error", 0,
  485. X           501, "syntax error", 0,
  486. X           530, "not logged in", 0,
  487. X
  488. X           421, "service unavailable, closing connection", 0);
  489. X    if( $ret != 1 ){
  490. X        print "    Failure on RETR command\n";
  491. X
  492. X        # shut down our end of the socket
  493. X        &ftp'close_data_socket;
  494. X
  495. X        return 0;
  496. X    }
  497. X
  498. X    # 
  499. X    # the data should be coming at us now
  500. X    #
  501. X
  502. X    # now accept
  503. X    accept(NS,S) || die "accept failed: $!";
  504. X
  505. X    #
  506. X    #  open the local fname
  507. X    #  concatenate on the end if restarting, else just overwrite
  508. X    if( !open(FH, ($restart ? '>>' : '>') . $loc_fname) ){
  509. X        print "    Cannot create local file $loc_fname\n";
  510. X
  511. X        # shut down our end of the socket
  512. X        &ftp'close_data_socket;
  513. X
  514. X        return 0;
  515. X    }
  516. X
  517. X#    while (<NS>) {
  518. X#        print FH ;
  519. X#    }
  520. X
  521. X    local( $start_time ) = time;
  522. X    local( $bytes, $lasthash, $hashes ) = (0, 0, 0);
  523. X    while( ($len = &ftp'read()) > 0 ){
  524. X        $bytes += $len;
  525. X        if( $strip_cr ){
  526. X            $ftp'buf =~ s/\r//g;
  527. X        }
  528. X#        if( $ftp_show ){
  529. X#            while( $bytes > ($lasthash + $ftp'hashevery) ){
  530. X#                print '#';
  531. X#                $lasthash += $ftp'hashevery;
  532. X#                $hashes++;
  533. X#                if( ($hashes % $ftp'hashnl) == 0 ){
  534. X#                    print "\n";
  535. X#                }
  536. X#            }
  537. X#        }
  538. X        print FH $ftp'buf;
  539. X    }
  540. X    close( FH );
  541. X
  542. X    # shut down our end of the socket
  543. X    &ftp'close_data_socket;
  544. X
  545. X    if( $len < 0 ){
  546. X        print "\n    timed out reading data!\n";
  547. X
  548. X        return 0;
  549. X    }
  550. X        
  551. X    if( $ftp_show ){
  552. X        if( $hashes && ($hashes % $ftp'hashnl) != 0 ){
  553. X            print "\n";
  554. X        }
  555. X        local( $secs ) = (time - $start_time);
  556. X        if( $secs <= 0 ){
  557. X            $secs = 1; # To avoid a devide by zero;
  558. X        }
  559. X
  560. X        local( $rate ) = int( $bytes / $secs );
  561. X        print "    Got $bytes bytes ($rate bytes/sec)\n";
  562. X    }
  563. X
  564. X    #
  565. X    # read the close
  566. X    #
  567. X
  568. X    $ret = &ftp'expect($timeout, 
  569. X        226, "Got file", 1,     # transfer complete, closing connection
  570. X            250, "Got file", 1,     # action completed
  571. X    
  572. X            110, "restart not supported", 0,
  573. X            425, "can't open data connection", 0,
  574. X            426, "connection closed, transfer aborted", 0,
  575. X            451, "action aborted, local error", 0,
  576. X        421, "service unavailable, closing connection", 0);
  577. X
  578. X    return $ret;
  579. X}
  580. X
  581. Xsub ftp'delete
  582. X{
  583. X    local( $rem_fname, $val ) = @_;
  584. X
  585. X    &ftp'send("DELE $rem_fname" );
  586. X    $val = &ftp'expect( $timeout, 
  587. X               250,"Deleted $rem_fname", 1,
  588. X               550,"Permission denied",0
  589. X               );
  590. X    return $val == 1;
  591. X}
  592. X
  593. Xsub ftp'deldir
  594. X{
  595. X    local( $fname ) = @_;
  596. X
  597. X    # not yet implemented
  598. X    # RMD
  599. X}
  600. X
  601. X# UPDATE ME!!!!!!
  602. X# Add in the hash printing and newline conversion
  603. Xsub ftp'put
  604. X{
  605. X    local( $loc_fname, $rem_fname ) = @_;
  606. X    local( $strip_cr );
  607. X    
  608. X    if ($loc_fname eq "") {
  609. X        $loc_fname = $rem_fname;
  610. X    }
  611. X    
  612. X    if( ! &ftp'open_data_socket() ){
  613. X        return 0;
  614. X    }
  615. X    
  616. X    &ftp'send("STOR $rem_fname");
  617. X    
  618. X    # 
  619. X    # the data should be coming at us now
  620. X    #
  621. X    
  622. X    local( $ret ) =
  623. X    &ftp'expect($timeout, 
  624. X        150, "sending $loc_fname", 1,
  625. X
  626. X        125, "data connection already open?", 0,
  627. X        450, "file unavailable", 0,
  628. X
  629. X        532, "need account for storing files", 0,
  630. X        452, "insufficient storage on system", 0,
  631. X        553, "file name not allowed", 0,
  632. X
  633. X        500, "syntax error", 0,
  634. X        501, "syntax error", 0,
  635. X        530, "not logged in", 0,
  636. X
  637. X        421, "service unavailable, closing connection", 0);
  638. X
  639. X    if( $ret != 1 ){
  640. X        # shut down our end of the socket
  641. X        &ftp'close_data_socket;
  642. X
  643. X        return 0;
  644. X    }
  645. X
  646. X
  647. X    # 
  648. X    # the data should be coming at us now
  649. X    #
  650. X    
  651. X    # now accept
  652. X    accept(NS,S) || die "accept failed: $!";
  653. X    
  654. X    #
  655. X    #  open the local fname
  656. X    #
  657. X    if( !open(FH, "<$loc_fname") ){
  658. X        print "    Cannot open local file $loc_fname\n";
  659. X
  660. X        # shut down our end of the socket
  661. X        &ftp'close_data_socket;
  662. X
  663. X        return 0;
  664. X    }
  665. X    
  666. X    while (<FH>) {
  667. X        print NS ;
  668. X    }
  669. X    close(FH);
  670. X    
  671. X    # shut down our end of the socket to signal EOF
  672. X    &ftp'close_data_socket;
  673. X    
  674. X    #
  675. X    # read the close
  676. X    #
  677. X    
  678. X    $ret = &ftp'expect($timeout, 
  679. X        226, "file put", 1,     # transfer complete, closing connection
  680. X        250, "file put", 1,     # action completed
  681. X    
  682. X        110, "restart not supported", 0,
  683. X        425, "can't open data connection", 0,
  684. X        426, "connection closed, transfer aborted", 0,
  685. X        451, "action aborted, local error", 0,
  686. X        551, "page type unknown", 0,
  687. X        552, "storage allocation exceeded", 0,
  688. X    
  689. X        421, "service unavailable, closing connection", 0);
  690. X    if( ! $ret ){
  691. X        print "    error putting $loc_fname\n";
  692. X    }
  693. X    return $ret;
  694. X}
  695. X
  696. Xsub ftp'restart
  697. X{
  698. X    local( $restart_point, $ret ) = @_;
  699. X
  700. X    &ftp'send("REST $restart_point");
  701. X
  702. X    # 
  703. X    # see what they say
  704. X
  705. X    $ret = &ftp'expect($timeout, 
  706. X               350, "restarting at $restart_point", 1,
  707. X               
  708. X               500, "syntax error", 0,
  709. X               501, "syntax error", 0,
  710. X               502, "REST not implemented", 2,
  711. X               530, "not logged in", 0,
  712. X               
  713. X               421, "service unavailable, closing connection", 0);
  714. X    return $ret;
  715. X}
  716. X
  717. X# Set the file transfer type
  718. Xsub ftp'type
  719. X{
  720. X    local( $type ) = @_;
  721. X
  722. X    &ftp'send("TYPE $type");
  723. X
  724. X    # 
  725. X    # see what they say
  726. X
  727. X    $ret = &ftp'expect($timeout, 
  728. X               200, "file type set to $type", 1,
  729. X               
  730. X               500, "syntax error", 0,
  731. X               501, "syntax error", 0,
  732. X               504, "Invalid form or byte size for type $type", 0,
  733. X               
  734. X               421, "service unavailable, closing connection", 0);
  735. X    return $ret;
  736. X}
  737. X
  738. X$site_command_check = 0;
  739. X@site_command_list = ();
  740. X
  741. X# routine to query the remote server for 'SITE' commands supported
  742. Xsub ftp'site_commands
  743. X{
  744. X    local( $ret );
  745. X    
  746. X    # if we havent sent a 'HELP SITE', send it now
  747. X    if( !$site_command_check ){
  748. X    
  749. X        $site_command_check = 1;
  750. X    
  751. X        &ftp'send( "HELP SITE" );
  752. X    
  753. X        # assume the line in the HELP SITE response with the 'HELP'
  754. X        # command is the one for us
  755. X        $ret = &ftp'expect( $timeout,
  756. X            ".*HELP.*", "", "\$1",
  757. X            214, "", "0",
  758. X            202, "", "0" );
  759. X    
  760. X        if( $ret eq "0" ){
  761. X            print "    No response from HELP SITE\n" if( $ftp_show );
  762. X        }
  763. X    
  764. X        @site_command_list = split(/\s+/, $ret);
  765. X    }
  766. X    
  767. X    return @site_command_list;
  768. X}
  769. X
  770. X# return the pwd, or null if we can't get the pwd
  771. Xsub ftp'pwd
  772. X{
  773. X    local( $ret, $cwd );
  774. X
  775. X    &ftp'send( "PWD" );
  776. X
  777. X    # 
  778. X    # see what they say
  779. X
  780. X    $ret = &ftp'expect( $timeout, 
  781. X#               "257.*\\\"(.*)\\\"", "working directory is \$2", "\$2",
  782. X               257, "working dir is", 1,
  783. X               500, "syntax error", 0,
  784. X               501, "syntax error", 0,
  785. X               502, "PWD not implemented", 0,
  786. X                       550, "file unavailable", 0,
  787. X
  788. X               421, "service unavailable, closing connection", 0 );
  789. X    if( $ret ){
  790. X        if( $ftp'response =~ /^257\s"(.*)"\s.*$/ ){
  791. X            $cwd = $1;
  792. X        }
  793. X    }
  794. X    return $cwd;
  795. X}
  796. X
  797. X# return 1 for success, 0 for failure
  798. Xsub ftp'mkdir
  799. X{
  800. X    local( $path ) = @_;
  801. X    local( $ret );
  802. X
  803. X    &ftp'send( "MKD $path" );
  804. X
  805. X    # 
  806. X    # see what they say
  807. X
  808. X    $ret = &ftp'expect( $timeout, 
  809. X               257, "made directory $path", 1,
  810. X               
  811. X               500, "syntax error", 0,
  812. X               501, "syntax error", 0,
  813. X               502, "MKD not implemented", 0,
  814. X               530, "not logged in", 0,
  815. X                       550, "file unavailable", 0,
  816. X
  817. X               421, "service unavailable, closing connection", 0 );
  818. X    return $ret;
  819. X}
  820. X
  821. X# return 1 for success, 0 for failure
  822. Xsub ftp'chmod
  823. X{
  824. X    local( $path, $mode ) = @_;
  825. X    local( $ret );
  826. X
  827. X    &ftp'send( sprintf( "SITE CHMOD %o $path", $mode ) );
  828. X
  829. X    # 
  830. X    # see what they say
  831. X
  832. X    $ret = &ftp'expect( $timeout, 
  833. X               200, "chmod $mode $path succeeded", 1,
  834. X               
  835. X               500, "syntax error", 0,
  836. X               501, "syntax error", 0,
  837. X               502, "CHMOD not implemented", 0,
  838. X               530, "not logged in", 0,
  839. X                       550, "file unavailable", 0,
  840. X
  841. X               421, "service unavailable, closing connection", 0 );
  842. X    return $ret;
  843. X}
  844. X
  845. X# rename a file
  846. Xsub ftp'rename
  847. X{
  848. X    local( $old_name, $new_name ) = @_;
  849. X    local( $ret );
  850. X
  851. X    &ftp'send( "RNFR $old_name" );
  852. X
  853. X    # 
  854. X    # see what they say
  855. X
  856. X    $ret = &ftp'expect( $timeout, 
  857. X
  858. X               350, "", 1,
  859. X               
  860. X               500, "syntax error", 0,
  861. X               501, "syntax error", 0,
  862. X               502, "RNFR not implemented", 0,
  863. X               530, "not logged in", 0,
  864. X                       550, "file unavailable", 0,
  865. X                       450, "file unavailable", 0,
  866. X               
  867. X               421, "service unavailable, closing connection", 0);
  868. X
  869. X
  870. X    # check if the "rename from" occurred ok
  871. X    if( $ret ) {
  872. X        &ftp'send( "RNTO $new_name" );
  873. X    
  874. X        # 
  875. X        # see what they say
  876. X    
  877. X        $ret = &ftp'expect( $timeout, 
  878. X    
  879. X                       250, "rename $old_name to $new_name", 1, 
  880. X
  881. X                   500, "syntax error", 0,
  882. X                   501, "syntax error", 0,
  883. X                   502, "RNTO not implemented", 0,
  884. X                   503, "bad sequence of commands", 0,
  885. X                   530, "not logged in", 0,
  886. X                           532, "need account for storing files", 0,
  887. X                           553, "file name not allowed", 0,
  888. X                   
  889. X                   421, "service unavailable, closing connection", 0);
  890. X    }
  891. X
  892. X    return $ret;
  893. X}
  894. X
  895. X# ------------------------------------------------------------------------------
  896. X# These are the lower level support routines
  897. X
  898. Xsub ftp'expectgot
  899. X{
  900. X    ($ftp'response, $ftp'fatalerror) = @_;
  901. X    if( $ftp_show ){
  902. X        print "    $ftp'response\n";
  903. X    }
  904. X}
  905. X
  906. X#
  907. X#  create the list of parameters for chat'expect
  908. X#
  909. X#  ftp'expect(time_out, {value, string_to_print, return value});
  910. X#     if the string_to_print is "" then nothing is printed
  911. X#  the last response is stored in $ftp'response
  912. X#
  913. X# NOTE: lmjm has changed this code such that the string_to_print is
  914. X# ignored and the string sent back from the remote system is printed
  915. X# instead.
  916. X#
  917. Xsub ftp'expect {
  918. X    local( $ret );
  919. X    local( $time_out );
  920. X    local( $expect_args );
  921. X    
  922. X    $ftp'response = '';
  923. X    $ftp'fatalerror = 0;
  924. X
  925. X    @expect_args = ();
  926. X    
  927. X    $time_out = shift(@_);
  928. X    
  929. X    while( @_ ){
  930. X        local( $code ) = shift( @_ );
  931. X        local( $pre ) = '^';
  932. X        if( $code =~ /^\d/ ){
  933. X            $pre =~ "[.|\n]*^";
  934. X        }
  935. X        push( @expect_args, "$pre(" . $code . " .*)\\015\\n" );
  936. X        shift( @_ );
  937. X        push( @expect_args, 
  938. X            "&ftp'expectgot( \$1, 0 ); " . shift( @_ ) );
  939. X    }
  940. X    
  941. X    # Treat all unrecognised lines as continuations
  942. X    push( @expect_args, "^(.*)\\015\\n" );
  943. X    push( @expect_args, "&ftp'expectgot( \$1, 0 ); 100" );
  944. X    
  945. X    # add patterns TIMEOUT and EOF
  946. X    
  947. X    push( @expect_args, 'TIMEOUT' );
  948. X    push( @expect_args, "&ftp'expectgot( \"timed out\", 1 ); 0" );
  949. X    
  950. X    push( @expect_args, 'EOF' );
  951. X    push( @expect_args, "&ftp'expectgot( \"remote server gone away\", 1 ); 0" );
  952. X    
  953. X    if( $ftp_show > 9 ){
  954. X        &printargs( $time_out, @expect_args );
  955. X    }
  956. X    
  957. X    $ret = &chat'expect( $time_out, @expect_args );
  958. X    if( $ret == 100 ){
  959. X        # we saw a continuation line, wait for the end
  960. X        push( @expect_args, "^.*\n" );
  961. X        push( @expect_args, "100" );
  962. X    
  963. X        while( $ret == 100 ){
  964. X            $ret = &chat'expect( $time_out, @expect_args );
  965. X        }
  966. X    }
  967. X    
  968. X    return $ret;
  969. X}
  970. X
  971. X#
  972. X#  opens NS for io
  973. X#
  974. Xsub ftp'open_data_socket
  975. X{
  976. X    local( $ret );
  977. X    local( $hostname );
  978. X    local( $sockaddr, $name, $aliases, $proto, $port );
  979. X    local( $type, $len, $thisaddr, $myaddr, $a, $b, $c, $d );
  980. X    local( $mysockaddr, $family, $hi, $lo );
  981. X    
  982. X    
  983. X    $sockaddr = 'S n a4 x8';
  984. X    chop( $hostname = `hostname` );
  985. X    
  986. X    $port = "ftp";
  987. X    
  988. X    ($name, $aliases, $proto) = getprotobyname( 'tcp' );
  989. X    ($name, $aliases, $port) = getservbyname( $port, 'tcp' );
  990. X    
  991. X#    ($name, $aliases, $type, $len, $thisaddr) =
  992. X#    gethostbyname( $hostname );
  993. X    ($a,$b,$c,$d) = unpack( 'C4', $chat'thisaddr );
  994. X    
  995. X#    $this = pack( $sockaddr, &main'AF_INET, 0, $thisaddr );
  996. X    $this = $chat'thisproc;
  997. X    
  998. X    socket(S, &main'PF_INET, &main'SOCK_STREAM, $proto ) || die "socket: $!";
  999. X    bind(S, $this) || die "bind: $!";
  1000. X    
  1001. X    # get the port number
  1002. X    $mysockaddr = getsockname(S);
  1003. X    ($family, $port, $myaddr) = unpack( $sockaddr, $mysockaddr );
  1004. X    
  1005. X    $hi = ($port >> 8) & 0x00ff;
  1006. X    $lo = $port & 0x00ff;
  1007. X    
  1008. X    #
  1009. X    # we MUST do a listen before sending the port otherwise
  1010. X    # the PORT may fail
  1011. X    #
  1012. X    listen( S, 5 ) || die "listen";
  1013. X    
  1014. X    &ftp'send( "PORT $a,$b,$c,$d,$hi,$lo" );
  1015. X    
  1016. X    return &ftp'expect($timeout, 200, "", 1,
  1017. X    
  1018. X        500, "syntax error", 0,
  1019. X        501, "syntax error", 0,
  1020. X        530, "not logged in", 0,
  1021. X        421, "service unavailable, closing connection", 0);
  1022. X}
  1023. X    
  1024. Xsub ftp'close_data_socket
  1025. X{
  1026. X    close(NS);
  1027. X}
  1028. X
  1029. Xsub ftp'send
  1030. X{
  1031. X    local($send_cmd) = @_;
  1032. X    if( $send_cmd =~ /\n/ ){
  1033. X        print "    ERROR, \\n in send string for $send_cmd\n";
  1034. X    }
  1035. X    
  1036. X    if( $ftp_show ){
  1037. X        local( $sc ) = $send_cmd;
  1038. X
  1039. X        if( $send_cmd =~ /^PASS/
  1040. X           && $remote_user !~ /^(ftp|anonymous)$/i ){
  1041. X            $sc = "PASS <somestring>";
  1042. X        }
  1043. X        print "    ---> $sc\n";
  1044. X    }
  1045. X    
  1046. X    &chat'print( "$send_cmd\r\n" );
  1047. X}
  1048. X
  1049. Xsub ftp'printargs
  1050. X{
  1051. X    while( @_ ){
  1052. X        print shift( @_ ) . "\n";
  1053. X    }
  1054. X}
  1055. X
  1056. Xsub ftp'filesize
  1057. X{
  1058. X    local( $fname ) = @_;
  1059. X
  1060. X    if( ! -f $fname ){
  1061. X        return -1;
  1062. X    }
  1063. X
  1064. X    return (stat( _ ))[ 7 ];
  1065. X    
  1066. X}
  1067. X
  1068. X# make this package return true
  1069. X1;
  1070. END_OF_FILE
  1071.   if test 22946 -ne `wc -c <'mserv-3.1/ftp.pl'`; then
  1072.     echo shar: \"'mserv-3.1/ftp.pl'\" unpacked with wrong size!
  1073.   fi
  1074.   # end of 'mserv-3.1/ftp.pl'
  1075. fi
  1076. if test -f 'mserv-3.1/ms_config.pl' -a "${1}" != "-c" ; then 
  1077.   echo shar: Will not clobber existing file \"'mserv-3.1/ms_config.pl'\"
  1078. else
  1079.   echo shar: Extracting \"'mserv-3.1/ms_config.pl'\" \(12646 characters\)
  1080.   sed "s/^X//" >'mserv-3.1/ms_config.pl' <<'END_OF_FILE'
  1081. X# mserv_config.pl -- config info for mail server
  1082. X# Author          : Johan Vromans
  1083. X# Created On      : ***
  1084. X# Last Modified By: Johan Vromans
  1085. X# Last Modified On: Sat Jan  2 14:18:04 1993
  1086. X# Update Count    : 74
  1087. X# Status          : OK
  1088. X
  1089. X################ Preamble ################
  1090. X #
  1091. X # Owner of the mail server. Must be set.
  1092. X # This user need no special privileges, except for write access to the
  1093. X # mail server files, and read access to the archives.
  1094. X # It will get email about problem situations.
  1095. X$mserv_owner = "mserv";
  1096. X
  1097. X################ Reply section ################
  1098. X #
  1099. X # The mail server sends replies to the sender of messages.
  1100. X # It could use the current user id as its own address, but usually it
  1101. X # is better to substitute something else to prevent bounced mail
  1102. X # messages clobbering your system.
  1103. X #
  1104. X # Your domain. Unfortunately there is no reliable way of fetching this
  1105. X # from the system info.
  1106. X$domain = "mh.nl";
  1107. X #
  1108. X # Sender of the messages. Try to prevent annoying bounced messages.
  1109. X$mserv_sender = (getpwnam($mserv_owner))[6] || "Mail Server";
  1110. X$sender = "From: $mserv_sender <bit-bucket@$domain>";
  1111. X #
  1112. X # Mail server bcc id.
  1113. X # If set, this user gets a Bcc of each request. Can be used for
  1114. X # accounting, or to keep track of functionality.
  1115. X$mserv_bcc = $mserv_owner;
  1116. X #
  1117. X # Sendmail functionality. Will be called with the recipients on the
  1118. X # command line, and a pre-formatted message (including some headers) on 
  1119. X # standard input.
  1120. X # NOTE: Do not use `-t' if you're running smail3. It will exclude the
  1121. X #    named recipients from delivery.
  1122. X$sendmail = "/usr/lib/sendmail";
  1123. X #
  1124. X # Optional mail headers.
  1125. X # Undefine if not wanted.
  1126. X@x_headers = ("X-Server: $my_package [$my_name $my_version]",
  1127. X          "X-Info: Send mail to <postmaster@$domain>");
  1128. X #
  1129. X # Sometimes system users (daemons) can send unsollicited messages.
  1130. X # The next list holds the names of users whose messages will be 
  1131. X # discarded without notice. 
  1132. X # Leave it undefined if this feature is not needed.
  1133. X@black_list = ("root", "uucp", "mailer", "MAILER-DAEMON", "news",
  1134. X           "daemon", "demon", "deliver", "sendmail");
  1135. X #
  1136. X # Define $black_list_warning if you only want to supply a warning.
  1137. X$black_list_warning = 1;
  1138. X
  1139. X################ Listener section ################
  1140. X #
  1141. X # When a mail message is received by the mail server, it is piped into
  1142. X # program 'listener'.
  1143. X # This program changes uid to the mail server owner, and executes
  1144. X # the 'process' program.
  1145. X #
  1146. X # Define $have_setruid if you have the setruid/setguid system calls.
  1147. X # In this case, the program needs to be installed setuid to the
  1148. X # mail server owner. If you do not define $have_setruid, the program has to
  1149. X # be installed setuid 'root'.
  1150. X$have_setruid = 1;
  1151. X #
  1152. X # Define $have_setenv if you have the setenv(3) library call. Using
  1153. X # setenv is optional.
  1154. X$have_setenv = 1;
  1155. X #
  1156. X # If you $have_setruid, you may define $use_uid also.
  1157. X # In this case the getpw* routines will not be used and
  1158. X # your executable will be significantly smaller and faster.
  1159. X$use_uid = 1;
  1160. X
  1161. X################ Email section ################
  1162. X #
  1163. X # The default strategy for the mail server is to transfer requests
  1164. X # via email. If you set this to zero, $uucp must be defined, and the
  1165. X # server will deliver via UUCP only.
  1166. X$email = 1;
  1167. X #
  1168. X # Sendmail functionality. Will be called with the recipients on the
  1169. X # command line, and a pre-formatted message (including some headers) on 
  1170. X # standard input.
  1171. X # NOTE: Do not use `-t' if you're running smail3. It will exclude the
  1172. X #    named recipients from delivery.
  1173. X # Used by "dorequest" to transmit chunks of data via email.
  1174. X$chunkmail = "/usr/lib/sendmail -odq";
  1175. X #
  1176. X # The minimum,default,maximum size of email chunks in K.
  1177. X@email_limits = (10,64,1024);
  1178. X #
  1179. X # To prevent overloading the system by firing too many sendmails,
  1180. X # use this amount to sleep between sending chunks.
  1181. X$mailer_delay = 30;
  1182. X
  1183. X################ UUCP section ################
  1184. X #
  1185. X # The mail server can transfer requests via uucp to systems that are
  1186. X # connected that way. This is very efficient compared to email, e.g. 
  1187. X # no encoding overhead.
  1188. X #
  1189. X # Define '$uucp' if you want to use the uucp feature.
  1190. X # Append uucp grade, if desired (and your uucp supports it).
  1191. X # If you do not define $uucp, requests will be send via email.
  1192. X$uucp = "/usr/bin/uucp -ga";
  1193. X #
  1194. X # Prefer UUCP transfer, if possible.
  1195. X$prefer_uucp = 1;
  1196. X #
  1197. X # Uucp host names can be checked for validity, if desired.
  1198. X # This is how to get a list of uucp host names. 
  1199. X # Set it to empty if you do not want to check the host names.
  1200. X$uuname = "/usr/bin/uuname";    # Check host names.
  1201. X #$uuname = "";            # Do not check host names.
  1202. X #
  1203. X # The minimum,default,maximum size of uucp chunks in K.
  1204. X@uucp_limits = (10,256,2048);
  1205. X #
  1206. X # Your uucp host name, if appropriate
  1207. X#$uuname = "sun4nl";        # static
  1208. Xchop ($uucp_name = `uuname -l`) if defined $uucp;    # dynamic
  1209. X
  1210. X################ FTP section ################
  1211. X #
  1212. X # The mail server can fetch files via FTP.
  1213. X$ftp = 1;
  1214. X #
  1215. X # The mail server tries to cache files retrieved via FTP, so
  1216. X # subsequent requests can be retrieved from the cache.
  1217. X # Before transferring a file from the cache, the file is verified to
  1218. X # matche the file on the FTP host.
  1219. X # Define $ftp_cache to specify where to cache the transferred files.
  1220. X # Do not define it to disable caching.
  1221. X$ftp_cache = "$libdir/ftp";
  1222. X #
  1223. X # Number of days a file is kept in the cache. Zero means: forever.
  1224. X # Time is measured since last access.
  1225. X$ftp_keep = 8;
  1226. X #
  1227. X # To reduce overhead, FTP requests may be restricted delivery via UUCP.
  1228. X$ftp_uucp_only = 1;
  1229. X
  1230. X################ Archives section ################
  1231. X #
  1232. X # Where to find the archive entries.
  1233. X@libdirs = ("/usr/local/src", "/beethoven/arch", "/users/jv/PD");
  1234. X # Please add mail server 'pub'!
  1235. Xpush (@libdirs, "$libdir/pub");
  1236. X #
  1237. X # Extensions we recognize. See "$dofilesearch" below.
  1238. X@exts = (".TZ", ".tar.Z", ".tar", ".shar.Z", ".shar", ".Z",
  1239. X     ".zoo", ".zip", ".arc", ".sit");
  1240. X
  1241. X################ Search strategies ################
  1242. X #
  1243. X # $dofilesearch: 
  1244. X #   Look for file: XXX must exist as file XXX in some lib dir.
  1245. X #   Known extensions are also tried.
  1246. X #   This is default if no other strategies are selected.
  1247. X #
  1248. X # $doindexsearch:
  1249. X #   Lookup XXXNNNYYY in $indexfile. 
  1250. X #   If $indexfile is a relative filename, every lib dir is supposed to
  1251. X #   have one. 
  1252. X #   If $indexfile is an absolute filename, the location it appears in
  1253. X #   will be considered part of the archives. This can be overridden with
  1254. X #   $indexlib.
  1255. X #
  1256. X # $dodirsearch:
  1257. X #   Look in dir: XXX or XXXNNNYYY (where NNN is a version indicator,
  1258. X #   e.g. '-1.02' and YYY a known extension, e.g. '.tar.Z') must exist
  1259. X #   in some lib dir, or subdir XXXNNN.
  1260. X #   Example: 'gcc' matches 'gcc', 'gcc.tar.Z', 'gcc-2.1.tar.Z',
  1261. X #            'gcc-2.1/gcc.tar.Z' etc.
  1262. X #
  1263. X # If your index matches the archives (as specified in @libdirs), you
  1264. X # can safely set $dodirsearch to 0.
  1265. X #
  1266. X$indexfile = "ix.codes";    # index file per archive directory
  1267. X#$indexfile = "$libdir/ix.codes";    # separate index file 
  1268. X#$indexlib  = $libdirs[0];        # archive for index file
  1269. X #
  1270. X # Subdirs of libdirs we do NOT want in the index files.
  1271. X # This is a list of gfind regexps, one per corresponding archive lib.
  1272. X # This is used by `makeindex' only.
  1273. X@libprunes = ();
  1274. X #
  1275. X$dofilesearch = 1;
  1276. X$doindexsearch = defined $indexfile;
  1277. X$dodirsearch = 1;
  1278. X #
  1279. X # If doindexsearch is selected, index searches can return a huge amount
  1280. X # of information. Therefore enforce a limit on the max. number of lines
  1281. X # an index request can return. Zero means: no limit.
  1282. X # Each time an index search exceeds the limit, it is lowered to half the 
  1283. X # value it had. This is to avoid excessive results.
  1284. X$maxindexlines = 200;
  1285. X #
  1286. X # Set auto_compress to 1 if a request for 'file.Z' is honoured if
  1287. X # 'file.Z' does not exists, but 'file' is found. 
  1288. X # 'file' will be compressed before transfer.
  1289. X # Set it to 2 if 'file.Z' may even result in 'file.shar.Z' or 'file.zoo.Z'...
  1290. X$auto_compress = 1;
  1291. X
  1292. X################ The mail server files ################
  1293. X #
  1294. X # No need to change these, I suppose.
  1295. X #
  1296. X # Where to store requests.
  1297. X$queue = $libdir . "/queue";
  1298. X # Where to log. Undefine if you do not want logging.
  1299. X # Note -- you can override this at run-time with 'doreqest -nolog'.
  1300. X #         'chmod -w $logfile' also works.
  1301. X$logfile = $libdir . "/logfile";
  1302. X # Lock file to guard against multiple executions of 'dorequest'.
  1303. X$lockfile = $libdir . "/lockfile";
  1304. X # notes file. Will be prepended to each confirmation message.
  1305. X # NOTE: if you change this, you'll need to change the Makefile also.
  1306. X$notesfile = $libdir . "/mserv.notes";
  1307. X # hints file. Will be appended to each confirmation message.
  1308. X # NOTE: if you change this, you'll need to change the Makefile also.
  1309. X$hintsfile = $libdir . "/mserv.hints";
  1310. X
  1311. X################ Locking section ################
  1312. X #
  1313. X # Select a locking method. Not selecting a locking method
  1314. X # voids your warranty.
  1315. X #
  1316. X # fcntl(2) locking. Requires "errno.ph" and "fcntl.ph".
  1317. X$lock_fcntl = 1;
  1318. X #
  1319. X # BSD style flock(2). Requires "errno.ph" and "sys/file.h".
  1320. X#$lock_flock = 1;
  1321. X #
  1322. X # lockf(2) locking. Requires "errno.ph", "unistd.ph" and "sys/syscall.ph".
  1323. X#$lock_lockf = 1;
  1324. X
  1325. X################ Encoding programs ################
  1326. X #
  1327. X # Default encoding. Select one of B, U, D, X and make sure the
  1328. X # corresponding encoding tool exists.
  1329. X$default_encoding = "U";    # uuencode
  1330. X #
  1331. X # Encoding programs. Supply a full pathname.
  1332. X # Encoding commands will be disallowed if the corresponding
  1333. X # encoding program is not available.
  1334. X # Since uuencode is fixed, it should better be there!
  1335. X$btoa     = "/usr/local/bin/btoa";    # btoa/atob
  1336. X$uuencode = "/usr/bin/uuencode";    # uu{en.de}code
  1337. X$uue      = "/usr/local/bin/uue";     # Dumas uue/uud program
  1338. X$xxencode = "/usr/local/bin/xxencode";     # xx{en.de}code
  1339. X
  1340. X################ Index section ################
  1341. X #
  1342. X # The following are only needed if you select indexsearch.
  1343. X # `makeindex' uses the GNU find program and locate tools.
  1344. X # The actual index lookup is performed by GNU locate 3.6 (or later)
  1345. X # or a customized version of GNU locate 3.5. In the latter case,
  1346. X # you need to "make ixlookup" and "make install-ixlookup".
  1347. X$gfind = "/usr/local/bin/gfind";
  1348. X # The GNU locate library (used to find bigram and code).
  1349. X$locatelib = "/usr/local/lib/locate";
  1350. X#$ixlookup = $libdir . "/ixlookup";    # based on GNU locate 3.5
  1351. X$ixlookup = "/usr/local/bin/locate";    # as of GNU locate 3.6
  1352. X
  1353. X################ Packing section ################
  1354. X #
  1355. X # The following are only needed if you want to support the packing 
  1356. X # of directories.
  1357. X #
  1358. X # Max number of blocks in a directory (as returned by 'du -s').
  1359. X # Undefine (or set to zero) if you do not want to support packing.
  1360. X$packing_limit = 4100;
  1361. X #
  1362. X # Set $auto_packing if a request for 'foo.tar.Z' may automatically
  1363. X # pack directory 'foo'.
  1364. X$auto_packing = 1;
  1365. X #
  1366. X # Tools.
  1367. X$du       = "/bin/du";            # get size of dir
  1368. X$find     = "/usr/local/bin/gfind";    # find
  1369. X # If you do not have 'pdtar', undefine it and the mail server will use
  1370. X # $tar and $compress instead.
  1371. X$pdtar    = "/usr/local/bin/pdtar";    # create compressed ustar
  1372. X$tar      = "/bin/tar";            # if no $pdtar...
  1373. X$compress = "/usr/ucb/compress";    # if no $pdtar...
  1374. X$zoo      = "/usr/local/bin/zoo";    # zoo
  1375. X$zip      = "/usr/local/bin/zip";    # zip
  1376. X
  1377. X################ Local commands section ################
  1378. X #
  1379. X # Command to produce a useful listing of files.
  1380. X$dircmd = "/bin/ls -lL";
  1381. X #
  1382. X # Command to call Archie.
  1383. X$archie = "archie";
  1384. X #
  1385. X # Limit (in K) for command output to be included in the feedback
  1386. X # mail.  If it is bigger, it will be compressed and transferred.
  1387. X # Zero disables the limit.
  1388. X$fb_limit = 8;
  1389. X #
  1390. X # Define $compress to the name of the compress command.
  1391. X # It should read from stdin and write to stdout.
  1392. X # This is needed for auto-compress and compress/tar functionality.
  1393. X$compress = "/usr/ucb/compress";
  1394. X
  1395. X################ Miscellaneous ################
  1396. X #
  1397. X # Working directory. Should have space for at least 1.5 times the
  1398. X # biggest file in the archives...
  1399. X #
  1400. X$tmpdir = $ENV{"TMPDIR"} || "/usr/tmp";
  1401. X
  1402. X # Should "dorequest" be run automatically after completion of
  1403. X # "process"?
  1404. X$auto_runrequest = 1;
  1405. X
  1406. X # Shall we be nice? This applies to the processing of the requests,
  1407. X # as well as to the queue run. Legitimate values are -20..20, but
  1408. X # only the superuser can raise the priority using negative values.
  1409. X$nice = 10;
  1410. X
  1411. X # It is possible to add user defined commands to the mail server.
  1412. X # See the documentation for details.
  1413. X#$cmd_extend = $libdir . "/userdefs.pl";
  1414. X
  1415. X # For debugging, it is sometimes necessary to trace the mail headers.
  1416. X # Note: the $trace_file must exist.
  1417. X$trace_headers = 0;
  1418. X$trace_file = $libdir . "/tracefile";
  1419. X
  1420. X################ End of configuation info ################
  1421. X
  1422. X1;
  1423. END_OF_FILE
  1424.   if test 12646 -ne `wc -c <'mserv-3.1/ms_config.pl'`; then
  1425.     echo shar: \"'mserv-3.1/ms_config.pl'\" unpacked with wrong size!
  1426.   fi
  1427.   # end of 'mserv-3.1/ms_config.pl'
  1428. fi
  1429. if test -f 'mserv-3.1/mserv.notesi' -a "${1}" != "-c" ; then 
  1430.   echo shar: Will not clobber existing file \"'mserv-3.1/mserv.notesi'\"
  1431. else
  1432.   echo shar: Extracting \"'mserv-3.1/mserv.notesi'\" \(0 characters\)
  1433.   sed "s/^X//" >'mserv-3.1/mserv.notesi' <<'END_OF_FILE'
  1434. END_OF_FILE
  1435.   if test 0 -ne `wc -c <'mserv-3.1/mserv.notesi'`; then
  1436.     echo shar: \"'mserv-3.1/mserv.notesi'\" unpacked with wrong size!
  1437.   fi
  1438.   # end of 'mserv-3.1/mserv.notesi'
  1439. fi
  1440. if test -f 'mserv-3.1/process.pl' -a "${1}" != "-c" ; then 
  1441.   echo shar: Will not clobber existing file \"'mserv-3.1/process.pl'\"
  1442. else
  1443.   echo shar: Extracting \"'mserv-3.1/process.pl'\" \(19935 characters\)
  1444.   sed "s/^X//" >'mserv-3.1/process.pl' <<'END_OF_FILE'
  1445. X#!/usr/local/bin/perl
  1446. X# process.pl -- 
  1447. X# SCCS Status     : @(#)@ process    3.67
  1448. X# Author          : Johan Vromans
  1449. X# Created On      : ***
  1450. X# Last Modified By: Johan Vromans
  1451. X# Last Modified On: Sat Jan  2 14:14:45 1993
  1452. X# Update Count    : 672
  1453. X# Status          : Going steady.
  1454. X
  1455. X# This program processes mail messages, and enqueues requests for
  1456. X# the mail server.
  1457. X#
  1458. X# For options and calling, see subroutine 'usage'.
  1459. X#
  1460. X$my_name = "process";
  1461. X$my_version = "3.67";
  1462. X#
  1463. X################ Common stuff ################
  1464. X
  1465. X$libdir = $ENV{"MSERVLIB"} || "/usr/local/lib/mserv";
  1466. Xunshift (@INC, $libdir);
  1467. X
  1468. X################ Options handling ################
  1469. X
  1470. X$opt_interactive = -t;
  1471. X&options if @ARGV > 0 && $ARGV[0] =~ /^-+[^-]+/;
  1472. X@ARGV = ("-") unless @ARGV > 0;
  1473. X$trace_headers = 1 if defined $opt_trace_headers;
  1474. X$interactive = $opt_interactive || defined $opt_i0;
  1475. X
  1476. X################ More common stuff ################
  1477. X
  1478. X# Require common here, so $opt_config can be used to select an
  1479. X# alternate configuration file.
  1480. Xrequire "ms_common.pl";
  1481. X
  1482. X################ Setting up ################
  1483. X
  1484. Xif ( $interactive ) {
  1485. X    if ( defined $opt_i0 ) {
  1486. X    # Attach STDOUT to STDIN.
  1487. X    close (STDOUT);
  1488. X    open (STDOUT, ">&0");
  1489. X    }
  1490. X    require "ctime.pl";
  1491. X    print STDOUT ("$mserv_sender ($my_package) ready.\n");
  1492. X    local ($t) = &ctime (time);
  1493. X    chop ($t);
  1494. X    print STDOUT ("Local time is $t.\n");
  1495. X    select (STDOUT);
  1496. X    $| = 1;
  1497. X}
  1498. Xelse {
  1499. X    # All output goes to STDOUT, and will be mailed to the requestor.
  1500. X    # Create a temp file to catch all.
  1501. X    $tmpfile = &fttemp;
  1502. X    open (STDOUT, ">" . $tmpfile) unless $opt_debug;
  1503. X}
  1504. X# Catch stderr also.
  1505. Xopen (STDERR, ">&STDOUT");
  1506. X
  1507. X# Motd.
  1508. X&include ($notesfile);
  1509. X
  1510. X$errflag = 0;
  1511. X$didhelp = 0;
  1512. X$needhelp = 0;
  1513. X
  1514. X# Turn extensions into pattern.
  1515. X($extpat = "(" . join("|", @exts) . ")") =~ s/\./\\./g;
  1516. X
  1517. X# Search strategy.
  1518. X$dofilesearch = 1 unless $dodirsearch || $doindexsearch;
  1519. X
  1520. Xrequire "$libdir/rfc822.pl";
  1521. X
  1522. X# Defaults from RFC822 mail headers.
  1523. X$h_from = $h_reply = "";
  1524. X
  1525. X# Defaults from UUCP From_ header.
  1526. X# Note that these will only be set if the host is existent and reachable,
  1527. X# and the user name appears to be good-looking.
  1528. X$h_uufrom = $h_uuhost = "";
  1529. X@hdrs = () if $trace_headers;
  1530. X
  1531. Xif ( !$interactive ) {
  1532. X    &start_read (shift(@ARGV)) ||
  1533. X    &die ("Cannot read input [$!]\n");
  1534. X}
  1535. X
  1536. X# UUCP "From_" line...
  1537. Xif ( defined $rfc822'line_in_cache && $rfc822'line_in_cache =~ /^From (\S+) / ) {
  1538. X    local ($try) = $1;
  1539. X    local (@h);
  1540. X
  1541. X    push (@hdrs, $rfc822'line_in_cache), chop $hdrs[0] if $trace_headers;
  1542. X
  1543. X    print STDOUT ("Processing UUCP header...\n");
  1544. X
  1545. X    $try = $1 . '!' . $try
  1546. X    if $rfc822'line_in_cache =~ /remote from (\S+)$/; #';
  1547. X        
  1548. X    # UUCP defaults...
  1549. X    @h = split ('!', $try);
  1550. X
  1551. X    # Sometimes the system name is prepended.
  1552. X    shift (@h) if $h[0] eq $uucp_name;
  1553. X
  1554. X    # For safety, we'll only accept good looking addresses.
  1555. X    if ( @h == 2 && $h[1] =~ /^\w[-\w.]*$/ &&
  1556. X    &check_uucp_name ($h[0], 1) ) {
  1557. X
  1558. X    # We have a valid UUCP name, and a good looking user name.
  1559. X    # We'll accept is as a default return address.
  1560. X    ($h_uuhost, $h_uufrom) = @h;
  1561. X    $h_from = join ('!', @h);
  1562. X    print STDOUT ("=> Return address (UUCP): \"$h_from\"\n");
  1563. X    push (@hdrs, "=> Return address (UUCP): \"$h_from\"")
  1564. X        if $trace_headers;
  1565. X    }
  1566. X    else {
  1567. X    &warning ("Unusable UUCP header", $rfc822'line_in_cache);    #');
  1568. X    push (@hdrs, "=> WARNING: Unusable UUCP header") if $trace_headers;
  1569. X    }
  1570. X    undef $rfc822'line_in_cache;    #';
  1571. X}
  1572. X
  1573. Xif ( !$interactive ) {
  1574. X    # Scan RFC822 headers, extracting From: and Reply-To: info.
  1575. X    print STDOUT ("Processing mail headers...\n");
  1576. X    while ( $res = &read_header ) {
  1577. X    last if $res == $rfc822'EMPTY_LINE;    #';
  1578. X    push (@hdrs, $rfc822'line) if $trace_headers;    #');
  1579. X    next unless $res == $rfc822'VALID_HEADER;    #';
  1580. X    $rfc822'header =~ tr/[A-Z]/[a-z]/;        #';
  1581. X    $h_from = $rfc822'contents if $rfc822'header eq "from";
  1582. X    $h_reply = $rfc822'contents if $rfc822'header eq "reply-to";
  1583. X    }
  1584. X
  1585. X    # Preset sender info.
  1586. X    $h_from = $h_reply if $h_reply;
  1587. X    $v_sender = $h_from;
  1588. X    &parse_addresses ($h_from);
  1589. X    if ( @rfc822'addresses == 1 ) {        #'){
  1590. X    $h_from = $rfc822'addresses[0];    #';
  1591. X    $v_sender = $rfc822'addr_comments{$h_from} || $h_from;    #';
  1592. X    }
  1593. X}
  1594. X
  1595. X# Setup defaults.
  1596. X&reset;
  1597. X
  1598. Xif ( !$interactive ) {
  1599. X    print STDOUT ("=> Default return address: \"$sender\"\n");
  1600. X
  1601. X    # Check the sender against the list of system accounts.
  1602. X    &validate_recipient ($sender, 2);
  1603. X
  1604. X    push (@hdrs, "=> Return address: \"$sender\"") if $trace_headers;
  1605. X
  1606. X    if ( $trace_headers && defined $trace_file && $trace_file ) {
  1607. X    if (open (TRACE, ">>$trace_file")) {
  1608. X        if ( &locking (*TRACE, 1) == 1 ) {
  1609. X        seek (TRACE, 0, 2);
  1610. X        print TRACE (join ("\n", @hdrs), "\n\n");
  1611. X        close (TRACE);
  1612. X        }
  1613. X    }
  1614. X    }
  1615. X
  1616. X    print STDOUT ("\nProcessing message contents...\n\n");
  1617. X    require "$libdir/pr_parse.pl";
  1618. X    &command_loop;
  1619. X    print STDOUT ("Your message has been processed.\n");
  1620. X    close (STDIN);
  1621. X}
  1622. Xelse {
  1623. X    require "$libdir/pr_parse.pl";
  1624. X    &interactive_loop;
  1625. X}
  1626. X
  1627. Xif ( $commands == 0 ) {
  1628. X    print STDOUT ("No commands were found.\n");
  1629. X    &help unless $interactive;
  1630. X}
  1631. Xelsif ( $errflag ) {
  1632. X    print STDOUT ("Number of errors detected = $errflag.\n",
  1633. X          "NO WORK WILL BE DONE.\n");
  1634. X    &help unless $didhelp;
  1635. X}
  1636. Xelse {
  1637. X    print STDOUT ("\n");
  1638. X
  1639. X    # Be nice and forgiving
  1640. X    eval { setpriority (0, $$, $nice) } if $nice;
  1641. X
  1642. X    # Subroutines index_loop and work_loop are contained in separate
  1643. X    # sources, since they may not always be needed. This speeds up
  1644. X    # processing and cuts down memory resources.
  1645. X    require "$libdir/pr_doindex.pl", &index_loop if @indexq > 0;
  1646. X    &search_loop if @searchq > 0;
  1647. X    if ( @workq > 0 ) {
  1648. X    require "$libdir/pr_dowork.pl";
  1649. X    &work_loop;
  1650. X    }
  1651. X    &help if $needhelp && !$didhelp;
  1652. X}
  1653. X
  1654. X&include ($hintsfile) 
  1655. X    unless $didhelp || $opt_debug || $opt_nomail || $interactive;
  1656. X
  1657. Xprint STDOUT ("\nMail Server finished.\n");
  1658. X
  1659. X# Send confirmation message to recipient.
  1660. X&confirm unless $interactive;
  1661. X
  1662. X# Startup the queue run in the background.
  1663. X&background_run ("$libdir/dorequest" . 
  1664. X         ($config_file ? " -config $config_file" : "") .
  1665. X         ($opt_trace ? " -trace" : "")) 
  1666. X    if -s $queue && $auto_runrequest && !$opt_debug && !$opt_noqueue;
  1667. X
  1668. Xexit (0);
  1669. X
  1670. X################ Subroutines ################
  1671. X
  1672. Xsub search {
  1673. X    local ($request, $wantall) = @_;
  1674. X
  1675. X    # This function returns an array of strings, each describing one
  1676. X    # possibility. Each description is a NUL-joined string with fields:
  1677. X    #   - the basename (used for sorting)
  1678. X    #   - the size
  1679. X    #   - the last modification date
  1680. X    #   - the name of the library (LIB)
  1681. X    #   - the part between library and basename
  1682. X    #
  1683. X    # If $wantall == TRUE, all possibilities are returned.
  1684. X    # If $wantall == FALSE, one possibility is returned if the filesearch
  1685. X    # (failing that, the directory search) locates exactly one file.
  1686. X    # Otherwise, all possibilities are returned.
  1687. X
  1688. X    local (@ret) = ();
  1689. X
  1690. X    if ( $dofilesearch ) {
  1691. X    foreach $lib ( @libdirs ) {
  1692. X        push (@ret, &filesearch ($lib, $request));
  1693. X    }
  1694. X    }
  1695. X
  1696. X    if ( $dodirsearch && ($wantall || @ret != 1)) {
  1697. X    require "$libdir/pr_dsearch.pl";
  1698. X    foreach $lib ( @libdirs ) {
  1699. X        push (@ret, &dirsearch ($lib, $request));
  1700. X    }
  1701. X    }
  1702. X
  1703. X    if ( $doindexsearch && ($wantall || @ret != 1)) {
  1704. X    require "$libdir/pr_isearch.pl";
  1705. X    if ( $indexfile =~ m|^/| ) {
  1706. X        local ($lib) = defined $indexlib ? $indexlib 
  1707. X        : (&fnsplit($indexfile))[0];
  1708. X        push (@ret, &indexsearch ($indexfile, $lib, $request));
  1709. X    }
  1710. X    else {
  1711. X        foreach $lib ( @libdirs ) {
  1712. X        push (@ret, &indexsearch ("$lib/$indexfile", $lib, $request));
  1713. X        }
  1714. X    }
  1715. X    }
  1716. X
  1717. X    if ( $opt_debug || $opt_trace ) {
  1718. X    @ret = reverse ( sort (@ret));
  1719. X    print STDOUT ("=> Search queue:\n");
  1720. X    local ($i) = 1;
  1721. X    foreach $entry ( @ret ) {
  1722. X        local (@a) = &zu ($entry);
  1723. X        printf STDOUT ("  %3d: %s %s %s %s:%s:%s\n", $i, 
  1724. X               $a[0], $a[1], $a[2], $a[3], $a[4], $a[0]);
  1725. X        $i++;
  1726. X    }
  1727. X    @ret;
  1728. X    }
  1729. X    else {
  1730. X    reverse ( sort (@ret));
  1731. X    }
  1732. X}
  1733. X
  1734. Xsub filesearch {
  1735. X
  1736. X    local ($libdir, $request) = @_;
  1737. X
  1738. X    # Locate an archive item $request in library $libdir.
  1739. X    # Eligible items are in the format XXX or
  1740. X    # XXX.EXT, where EXT is one of the known extensions.
  1741. X    #
  1742. X    # See "sub search" for a description of the return values.
  1743. X
  1744. X    local (@retval);        # return value
  1745. X    local (@a);            # to hold stat() result
  1746. X
  1747. X    # Normalize the request. 
  1748. X    # $tryfile will be the basename of the request.
  1749. X    # $subdir holds the part between $libdir and $tryfile.
  1750. X    local ($subdir, $tryfile) = &fnsplit ($request);
  1751. X    $subdir .= "/" if $subdir && $subdir !~ m|/$|;
  1752. X    $libdir .= "/" if $libdir && $libdir !~ m|/$|;
  1753. X
  1754. X    print STDOUT ("Try file $libdir$subdir$tryfile...\n") if $opt_debug;
  1755. X
  1756. X    # First attempt: see if the given file exists 'as is', with possible 
  1757. X    # extensions
  1758. X
  1759. X    foreach $ext ( "", @exts) {
  1760. X    if ( -f $libdir.$subdir.$tryfile.$ext && -r _ ) {
  1761. X        @a = stat (_);
  1762. X        print STDOUT ("File $libdir$subdir$tryfile$ext (found)\n")
  1763. X        if $opt_debug;
  1764. X        push (@retval, 
  1765. X          &zp ($tryfile.$ext, $a[7], $a[9], $libdir, $subdir));
  1766. X        last if $ext eq "";    # exact match prevails
  1767. X    }
  1768. X    }
  1769. X
  1770. X    return @retval;
  1771. X}
  1772. X
  1773. Xsub confirm {
  1774. X
  1775. X    # Send the contents of the temp file to the requestor.
  1776. X
  1777. X    # Close it, and reopen.
  1778. X    close (STDOUT);
  1779. X    open (MESSAGE, $tmpfile);
  1780. X
  1781. X    if ( $opt_debug || $opt_nomail ) {
  1782. X    open (MAILER, ">&STDERR");
  1783. X    }
  1784. X    else {
  1785. X    open (MAILER, "|$sendmail '$recipient' $mserv_bcc");
  1786. X    }
  1787. X
  1788. X    print MAILER ("To: $recipient\n",
  1789. X          "Subject: Request by $v_sender\n");
  1790. X
  1791. X    if ( defined @x_headers ) {
  1792. X    foreach $hdr ( @x_headers ) {
  1793. X        print MAILER ($hdr, "\n");
  1794. X    }
  1795. X    }
  1796. X    print MAILER ("\n");
  1797. X
  1798. X    local ($inhdrs) = 1;
  1799. X    while ( <MESSAGE> ) {
  1800. X
  1801. X    # Include everything before the message contents.
  1802. X    if ( $inhdrs ) {
  1803. X        print MAILER $_;
  1804. X        if ( $_ eq "Processing message contents...\n" ) {
  1805. X        $inhdrs = 0;
  1806. X        print MAILER "\n";
  1807. X        }
  1808. X        next;
  1809. X    }
  1810. X
  1811. X    # Suppress unrecognized stuff.
  1812. X    if ( $reset > 1 ) {
  1813. X        $reset-- if /^=> Resetting/;
  1814. X        if ( $reset > 1 ) {
  1815. X        print MAILER $' if /^Command: /;
  1816. X        }
  1817. X        else {
  1818. X        print MAILER $_;
  1819. X        }
  1820. X    }
  1821. X    else {
  1822. X        print MAILER $_;
  1823. X    }
  1824. X    }
  1825. X    close (MAILER);
  1826. X    close (MESSAGE);
  1827. X
  1828. X    # This aids in debugging...
  1829. X    rename ($tmpfile, $tmpdir . "/mserv.last");
  1830. X    unlink ($tmpfile);
  1831. X}
  1832. X
  1833. Xsub discard {
  1834. X    local ($msg) = @_;
  1835. X
  1836. X    # Discard the job.
  1837. X    # Do not attempt to send feedback except for a mailer error.
  1838. X    # This is used when requests are received from someone on the 
  1839. X    # 'black list'.
  1840. X
  1841. X    print STDOUT ("\nREQUEST DISCARDED: ", $msg, "\n");
  1842. X    close (STDOUT);
  1843. X
  1844. X    # This aids in debugging...
  1845. X    rename ($tmpfile, $tmpdir . "/mserv.last");
  1846. X    unlink ($tmpfile);
  1847. X
  1848. X    # The end of it all (silently)
  1849. X    exit (0);
  1850. X}
  1851. X
  1852. Xsub dolist {
  1853. X    local ($list_type, $query, *found) = (@_);
  1854. X    local ($entries) = 0;
  1855. X    local ($name, $size, $date, $lib, $subdir); # elements of @found
  1856. X    local ($prev);        # to suppress duplicates
  1857. X    local (@tm);        # for time conversions
  1858. X
  1859. X    $~ = "list_header";
  1860. X    write;
  1861. X    $~ = "list_format";
  1862. X    $: = " /";        # break filenames at logical places
  1863. X    $= = 99999;
  1864. X
  1865. X    # have we found something?
  1866. X    unless ( @found > 0 ) {
  1867. X    $size = $date = "";
  1868. X    $name = "***not found***";
  1869. X    write;
  1870. X    next;
  1871. X    }
  1872. X
  1873. X    $prev = "";
  1874. X    foreach $found ( @found ) {
  1875. X
  1876. X    ($name, $size, $date, $lib, $subdir) = &zu ($found);
  1877. X
  1878. X    # Avoid duplicates.
  1879. X    next if $lib.$subdir.$name eq $prev;
  1880. X    $prev = $lib.$subdir.$name;
  1881. X
  1882. X    # Normalize size and date, if needed.
  1883. X    $size = int(($size+1023)/1024) . "K" unless $size =~ /K$/;
  1884. X    if ( $date =~ /^T/ ) {
  1885. X        $date = $';
  1886. X    }
  1887. X    else {
  1888. X        @tm = localtime ($date);
  1889. X        $date = sprintf("%02d/%02d/%02d", 
  1890. X                1900+$tm[5], $tm[4]+1, $tm[3]);
  1891. X    }
  1892. X
  1893. X    $name = $subdir.$name;
  1894. X    write;
  1895. X    }
  1896. X}
  1897. X
  1898. Xsub search_loop {
  1899. X
  1900. X    print STDOUT ("Search results:\n");
  1901. X
  1902. X    foreach $query ( @searchq ) {
  1903. X
  1904. X    local (@found);        # return from search
  1905. X
  1906. X    # Locate them.
  1907. X    @found = &search ($query, 1);
  1908. X
  1909. X    # Print report.
  1910. X    &dolist ("Search", $query, *found);
  1911. X
  1912. X    }
  1913. X    @searchq = ();
  1914. X    print STDOUT ("\n");
  1915. X}
  1916. X
  1917. Xsub reset {
  1918. X    # Set defaults.
  1919. X    @workq = ();
  1920. X    @searchq = ();
  1921. X    @indexq = ();
  1922. X    $commands = 0;
  1923. X    $errflag = 0;
  1924. X    $method = '';
  1925. X    @limits = defined $email ? @email_limits : @uucp_limits;
  1926. X    $ftphost = '';
  1927. X
  1928. X    # Who sent this mail?
  1929. X    $sender = $h_from || "?";
  1930. X
  1931. X    # Who gets the replies?
  1932. X    $recipient = $sender;
  1933. X
  1934. X    # Destination for email transfers.
  1935. X    $destination = "";
  1936. X
  1937. X    # Tally.
  1938. X    $reset++;
  1939. X}
  1940. X
  1941. Xsub errmsg {
  1942. X  local (@msg) = @_;
  1943. X  print STDOUT ('>>>>>>>> Error: ', shift(@msg), "\n");
  1944. X  foreach $msg ( @msg ) {
  1945. X      print STDOUT ('         ', $msg, "\n");
  1946. X  }
  1947. X  # Most parsing routines use 'return &errmsg...', so make sure it
  1948. X  # errmsg returns a non-zero value.
  1949. X  ++$errflag;
  1950. X}
  1951. X
  1952. Xsub warning {
  1953. X  local (@msg) = @_;
  1954. X  print STDOUT ('>>>>>>>> Warning: ', shift(@msg), "\n");
  1955. X  foreach $msg ( @msg ) {
  1956. X      print STDOUT ('         ', $msg, "\n");
  1957. X  }
  1958. X  1;                # must be non-zero;
  1959. X}
  1960. X
  1961. Xsub include {
  1962. X    local ($file) = @_;
  1963. X    local (*F);
  1964. X    local ($ok) = 0;
  1965. X
  1966. X    if ( $interactive ) {
  1967. X    $ok = open (F, $file . 'i');
  1968. X    }
  1969. X    if ( $ok || ($ok = open (F, $file)) ) {
  1970. X    while ( <F> ) {
  1971. X        print STDOUT;
  1972. X    }
  1973. X    close (F);
  1974. X    }
  1975. X    $ok;
  1976. X}
  1977. X
  1978. X# Pseudo-record pack/unpack
  1979. Xsub zp { join ("\0", @_); }
  1980. Xsub zu { split (/\0/, $_[0]); }
  1981. X
  1982. Xsub email_defaults {
  1983. X    local ($dest) = @_;
  1984. X    $method = "M";
  1985. X    $destination = $dest;
  1986. X    push (@workq, &zp ("M", $destination));
  1987. X    &method_msg;
  1988. X    @limits = @email_limits;
  1989. X}
  1990. X
  1991. Xsub uucp_defaults {
  1992. X    local ($uuhost, $uupath, $uunote) = @_;
  1993. X    $uunote = $h_uufrom unless $uunote;
  1994. X    $uuhost = $h_uuhost unless $uuhost;
  1995. X    $uupath = "~uucp/receive/$h_uufrom" unless $uupath;
  1996. X
  1997. X    if ( &check_uucp_name ($uuhost) &&
  1998. X    &check_uucp_path ($uupath) ) {
  1999. X    $method = "U";
  2000. X    $uupath = $uuhost . '!' . $uupath;
  2001. X    push (@workq, &zp ("U", $uupath, $uunote));
  2002. X    &method_msg;
  2003. X    @limits = @uucp_limits;
  2004. X    }
  2005. X}
  2006. X
  2007. Xsub method_msg {
  2008. X    if ( $method eq 'U' ) {
  2009. X    print STDOUT ("=> Transfer via UUCP to \"$uupath\"\n");
  2010. X    print STDOUT ("=> (UUCP notification to \"$uunote\")\n");
  2011. X    }
  2012. X    elsif ( $method eq 'M' ) {
  2013. X    print STDOUT ("=> Transfer via email to \"$destination\"\n");
  2014. X    }
  2015. X    else {
  2016. X    &errmsg ("Please issue a MAIL or UUCP command first");
  2017. X    }
  2018. X}
  2019. X
  2020. Xsub ftp_defaults {
  2021. X
  2022. X    # Setup FTP stuff. Check if allowed.
  2023. X
  2024. X    ($ftphost) = @_;
  2025. X
  2026. X    if ( $ftphost eq '' ) {
  2027. X    &errmsg ("Missing FTP host name");
  2028. X    return 0;
  2029. X    }
  2030. X
  2031. X    local ($prefer_uucp) = $prefer_uucp | $ftp_uucp_only;
  2032. X    return 0 unless &setdefaults;
  2033. X
  2034. X    if ( $ftp_uucp_only && $method ne 'U' ) {
  2035. X    &errmsg ("FTP commands are only allowed when delivering via UUCP");
  2036. X    print STDOUT ("         (Issue an UUCP command first)\n");
  2037. X    $ftphost = '';
  2038. X    return 0;
  2039. X    }
  2040. X
  2041. X    push (@workq, &zp ('G', 'O', $ftphost));
  2042. X    print STDOUT ("=> FTP Connect to \"$ftphost\"\n");
  2043. X    1;
  2044. X}
  2045. X
  2046. Xsub setdefaults {
  2047. X
  2048. X    local (@_);
  2049. X
  2050. X    if ( $interactive && ! $method ) {
  2051. X    &method_msg;
  2052. X    return 0;
  2053. X    }
  2054. X
  2055. X    unless ( $recipient || $interactive ) {
  2056. X    $recipient = $sender;
  2057. X    print STDOUT ("=> Return address: \"$recipient\"\n");
  2058. X    }
  2059. X
  2060. X    unless ( $method ) {
  2061. X    if ( defined $uucp && $prefer_uucp && $h_uufrom && $h_uuhost ) {
  2062. X        &uucp_defaults;
  2063. X        print STDOUT ("=> If delivery via UUCP is not desired, ",
  2064. X              "issue a MAIL command first\n");
  2065. X    }
  2066. X    elsif ( defined $email ) {
  2067. X        &email_defaults ($destination || $recipient);
  2068. X    }
  2069. X    elsif ( defined $uucp ) {
  2070. X        if ( $h_uufrom && $h_uuhost ) {
  2071. X        &uucp_defaults;
  2072. X        }
  2073. X        else {
  2074. X        &errmsg ("Please issue a UUCP command first");
  2075. X        return 0;
  2076. X        }
  2077. X    }
  2078. X
  2079. X    unless ( $method ) {
  2080. X        &errmsg ("Sorry, can't transfer the requests to you",
  2081. X             "Issue a MAIL or UUCP command first");
  2082. X        return 0;
  2083. X    }
  2084. X    }
  2085. X    1;
  2086. X}
  2087. X
  2088. Xsub validate_recipient {
  2089. X    local ($addr, $todo) = @_;
  2090. X
  2091. X    # Validate a recipient name against the black list.
  2092. X    # Values for $todo:
  2093. X    #  0: return offending user name if invalid, otherwise return ''
  2094. X    #  1: as 0, but also supply warning
  2095. X    #  2: as 1, and discard job if configured to do so
  2096. X
  2097. X    local ($user);
  2098. X
  2099. X    return '' unless defined @black_list;
  2100. X    return '' if $interactive;
  2101. X
  2102. X    while ( ! defined $user ) {
  2103. X    $addr = $', next if $addr =~ /^@[^:]+:/;    # @domain,domain:...
  2104. X    $addr = $', next if $addr =~ /^[^!]+!/;        # host!...
  2105. X    $addr = $`, next if $addr =~ /@[^@]+$/;        # ...@domain
  2106. X    $user = $addr;
  2107. X    }
  2108. X
  2109. X    $addr = join ('!', @black_list);
  2110. X    return '' if index ("!\U$addr\E!", "!\U$user\E!") < $[;
  2111. X
  2112. X    if ( $todo >= 2 && ! $black_list_warning ) {
  2113. X    &discard ("User \"$user\" access refused");
  2114. X    # Not reached.
  2115. X    }
  2116. X
  2117. X    if ( $todo >= 1 ) {
  2118. X    &warning ("User \"$user\" will be refused access in the future",
  2119. X          "Please use a user account instead of a system account");
  2120. X    }
  2121. X
  2122. X    # Return the offending user name, so caller can provide a message.
  2123. X    return $user;
  2124. X}
  2125. X
  2126. Xsub die {
  2127. X    local ($msg) = "@_";
  2128. X    print STDOUT ($msg, "\n");
  2129. X    $sender = $sender || $mserv_owner || $mserv_bcc || "postmaster";
  2130. X    $mserv_bcc = $mserv_owner;
  2131. X    &confirm;
  2132. X    exit (1);
  2133. X}
  2134. X
  2135. Xsub background_run {
  2136. X    local ($cmd) = @_;
  2137. X
  2138. X    # Run $cmd in the background.
  2139. X
  2140. X    local ($pid);
  2141. X
  2142. X    if ( ($pid = fork) == 0 ) {
  2143. X
  2144. X    # Child process. Disable signals.
  2145. X    foreach $sig ( "HUP", "INT", "QUIT" ) {
  2146. X        $SIG{$sig} = "IGNORE";
  2147. X    }
  2148. X
  2149. X    # Fork another child to do the job.
  2150. X    if ( fork == 0 ) {
  2151. X        # Execute command. No way to signal failure.
  2152. X        exec $cmd;
  2153. X        exit (0);
  2154. X    }
  2155. X
  2156. X    }
  2157. X
  2158. X    # Wait for first child to complete. 
  2159. X    # This assures that the signals are armed before the parent can do
  2160. X    # harmful things.
  2161. X    waitpid ($pid, 0);
  2162. X}
  2163. X
  2164. Xsub check_uucp_name {
  2165. X    local ($host, $silent) = @_;
  2166. X    $host = $` if $host =~ /\.uucp/i;    # strip .UUCP
  2167. X    return 1 if $host eq $h_uuhost;     # already verified
  2168. X    return 1 unless $uuname ne "";
  2169. X    open ( UUNAME, $uuname . "|" );
  2170. X    local (@hosts) = <UUNAME>;
  2171. X    close (UUNAME);
  2172. X    @found = grep ( /^$host$/, @hosts );
  2173. X    return 1 if @found == 1;
  2174. X    &errmsg ("Unknown UUCP system name: \"$host\"") unless $silent;
  2175. X    $opt_debug;
  2176. X}
  2177. X
  2178. Xsub check_uucp_path {
  2179. X    local ($path) = @_;
  2180. X    # $path should start with slash or tilde.
  2181. X    return 1 if $path =~ /^[\/~]/;
  2182. X    &errmsg ("Invalid UUCP path name: \"$path\"");
  2183. X    0;
  2184. X}
  2185. X
  2186. Xsub options {
  2187. X    require "newgetopt.pl";
  2188. X    local ($opt_noi, $opt_nointeractive);
  2189. X    $opt_debug = $opt_trace = $opt_nomail = $opt_noqueue = $opt_help = 0;
  2190. X    if ( !&NGetOpt ("config=s", "trace_headers", "interactive", "i0",
  2191. X            "nointeractive", "noi",
  2192. X            "debug", "trace", "noqueue", "nomail", "help")
  2193. X    || $opt_help
  2194. X    || (@ARGV > 0 && !($opt_debug || $opt_trace || $opt_nomail))) {
  2195. X    &usage;
  2196. X    }
  2197. X    $config_file = $opt_config if defined $opt_config;
  2198. X    $opt_interactive = 0 if defined $opt_noi || defined $opt_nointeractive;
  2199. X
  2200. X}
  2201. X
  2202. Xsub usage {
  2203. X    require "ms_common.pl";
  2204. X    print STDERR <<EndOfUsage;
  2205. X$my_package [$my_name $my_version]
  2206. X
  2207. XUsage: $my_name [options] < mail-message
  2208. X
  2209. XOptions:
  2210. X    -config XX    load this config file instead of ms_config.pl
  2211. X    -help    this message
  2212. X    -interactive interactively read commands, and execute them
  2213. X    -nointeractive read an email message, even from terminal
  2214. X    -noqueue    process message, but do not enter request in the queue
  2215. X    -nomail    do not reply by email (testing only)
  2216. X    -debug    for debugging
  2217. X    -trace    for debugging
  2218. X    -trace_headers    for debugging
  2219. X
  2220. X'mail-message' should be RFC-822 conformant.
  2221. XEndOfUsage
  2222. X    exit (1);
  2223. X}
  2224. X
  2225. Xformat list_header =
  2226. X
  2227. X     Date       Size  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2228. X$list_type . ": " . $query
  2229. X  ----------  ------  ----------------------------
  2230. X.
  2231. Xformat list_format =
  2232. X  @<<<<<<<<< @>>>>>>  ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2233. X$date, $size, $name
  2234. X~~                      ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  2235. X$name
  2236. X.
  2237. X
  2238. Xsub help {
  2239. X    require 'pr_help.pl';
  2240. X    &do_help;
  2241. X    &include ($hintsfile) if $interactive;
  2242. X}
  2243. X
  2244. Xsub add_help {
  2245. X    # For user extensions, so they can give help too.
  2246. X    local ($cmd, @text) = @_;
  2247. X    @ext_help = () unless defined @ext_help;
  2248. X    push (@ext_help, "+$cmd", @text);
  2249. X}
  2250. X    
  2251. X1;
  2252. END_OF_FILE
  2253.   if test 19935 -ne `wc -c <'mserv-3.1/process.pl'`; then
  2254.     echo shar: \"'mserv-3.1/process.pl'\" unpacked with wrong size!
  2255.   fi
  2256.   # end of 'mserv-3.1/process.pl'
  2257. fi
  2258. echo shar: End of archive 3 \(of 6\).
  2259. cp /dev/null ark3isdone
  2260. MISSING=""
  2261. for I in 1 2 3 4 5 6 ; do
  2262.     if test ! -f ark${I}isdone ; then
  2263.     MISSING="${MISSING} ${I}"
  2264.     fi
  2265. done
  2266. if test "${MISSING}" = "" ; then
  2267.     echo You have unpacked all 6 archives.
  2268.     rm -f ark[1-9]isdone
  2269. else
  2270.     echo You still must unpack the following archives:
  2271.     echo "        " ${MISSING}
  2272. fi
  2273. exit 0
  2274. exit 0 # Just in case...
  2275.