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

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