1#!/usr/bin/perl -w
2##!~_~perlpath~_~
3#
4# Interchange version 5.6.3
5#
6# Copyright (C) 2002-2010 Interchange Development Group
7# Copyright (C) 1996-2002 Red Hat, Inc.
8# http://www.icdevgroup.org/
9#
10# This program was originally based on Vend 0.2 and 0.3
11# Copyright 1995 by Andrew M. Wilcox <amw@wilcoxsolutions.com>
12#
13# See the files 'README' and 'WHATSNEW' for information.
14#
15# This program is free software; you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation; either version 2 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public
26# License along with this program; if not, write to the Free
27# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
28# MA  02110-1301  USA.
29
30use strict;
31
32BEGIN {
33	select STDERR;
34	$| = 1;
35	select STDOUT;
36	$| = 1;
37
38	if ($ENV{INTERCHANGE_INSTALLPRIVLIB}) {
39		unshift @INC, $ENV{INTERCHANGE_INSTALLPRIVLIB};
40	}
41	else {
42		unshift @INC, '/usr/local/interchange/lib';
43#		unshift @INC, '~_~INSTALLPRIVLIB~_~';
44	}
45
46	if ($ENV{INTERCHANGE_INSTALLARCHLIB}) {
47		unshift @INC, $ENV{INTERCHANGE_INSTALLARCHLIB};
48	}
49	else {
50		unshift @INC, '/usr/local/interchange';
51#		unshift @INC, '~_~INSTALLARCHLIB~_~';
52	}
53}
54
55use Config;
56no Config;
57
58BEGIN {
59	require 5.008;
60
61	$ENV{PERL_SIGNALS} ||= 'unsafe';
62
63	$Global::Foreground = 1;
64
65	($Global::VendRoot = $ENV{MINIVEND_ROOT})
66		if defined $ENV{MINIVEND_ROOT};
67
68	no warnings 'void';
69	## This should only happen in "make test"
70	if($Global::VendRoot =~ m{/blib$}) {
71		shift @INC;
72		shift @INC;
73	}
74
75	$Global::VendRoot = $Global::VendRoot || '/usr/local/interchange';
76#	$Global::VendRoot = $Global::VendRoot || '~_~INSTALLARCHLIB~_~';
77
78	if( ($Config{usethreads} || $Config{useithreads} || $Config{use5005threads}) ) {
79		$Global::TryingThreads = 1;
80	}
81
82	if( $Global::TryingThreads and $] < 5.008_005 ) {
83		die "Interchange will not work with a thread-enabled perl older than Perl 5.8.5.\n";
84	}
85
86	if(-f "$Global::VendRoot/interchange.cfg") {
87		$Global::ExeName = 'interchange';
88		$Global::ConfigFile = 'interchange.cfg';
89	}
90	elsif(-f "$Global::VendRoot/minivend.cfg") {
91		$Global::ExeName = 'minivend';
92		$Global::ConfigFile = 'minivend.cfg';
93	}
94	else {
95		$Global::ExeName = 'interchange';
96		$Global::ConfigFile = 'interchange.cfg';
97	}
98
99	$Global::InitialErrorFile = $Global::ErrorFile = "$Global::VendRoot/error.log";
100
101	if($^O =~ /cygwin|win32/i) {
102		$Global::Windows = 1;
103	}
104
105	# Uncomment next line if you want to guarantee use of DB_File
106	#$ENV{MINIVEND_DBFILE} = 1;
107
108	# Uncomment next line in the unlikely event you want to ignore
109	# GDBM and DB_File and force use of SDBM.
110	#$ENV{MINIVEND_SDBM} = 1;
111
112	# Uncomment next line if you want to guarantee use of GDBM and not DB_File
113	#$ENV{MINIVEND_GDBM} = 1;
114
115	# Uncomment next line if you want to use no DBM, sessions
116	# stored in files and databases in memory (or SQL)
117	#$ENV{MINIVEND_NODBM} = 1;
118
119	# Uncomment next line if you want the ability to use ALL DBM.
120	# Otherwise we use only the first choice to save memory.
121	#$ENV{MINIVEND_ALLDBM} = 1;
122
123	# Uncomment next line if you DON'T want to use DBI, can
124	# save a bit on code size
125	#$ENV{MINIVEND_NO_DBI} = 1;
126
127	# Uncomment next line if you want to use the Storable
128	# module for storing session data. It improves session performance
129	# to a good degree. We will also do a bit of auto-detect below.
130	#$ENV{MINIVEND_STORABLE} = 1;
131
132	# Uncomment next line if you want to use the Storable
133	# module for storing database data. It improves GBDM/DB_File performance
134	# to a good degree. We will also do a bit of auto-detect below.
135	#$ENV{MINIVEND_STORABLE_DB} = 1;
136
137	# Uncomment AND SET next line to set PGP path to somewhere besides
138	# the Interchange user path
139	#$ENV{PGPPATH} = '/usr/local/pgp';
140
141	# Use the Storable module for storing data in DBM files.
142	if(-f "$Global::VendRoot/_session_storable") {
143		$ENV{MINIVEND_STORABLE} = 1;
144	}
145
146	if(-f "$Global::VendRoot/_db_storable") {
147		$ENV{MINIVEND_STORABLE_DB} = 1;
148	}
149
150	# Interchange can use syslog via the "logger" command
151	# This prevents parsing of the value, default is syslog off
152	$Global::SysLog		= '';
153}
154
155### END CONFIGURATION VARIABLES
156
157use vars qw($VERSION);
158require Exporter;
159
160BEGIN {
161	$VERSION = '5.6.3';
162}
163
164use Fcntl;
165
166# BSD, among others, defines sendmail to be in /usr/sbin, and
167# we want to make sure the program is there. Insert the location
168# of you sendmail binary (the configure script should do this)
169$Global::SendMailLocation = '' if ! $Global::SendMailLocation;
170$Global::SendMailLocation = ($Global::Windows and $Global::SendMailLocation) ||
171	($Global::SendMailLocation and -x $Global::SendMailLocation and $Global::SendMailLocation) ||
172	(-x '/usr/sbin/sendmail' and '/usr/sbin/sendmail') ||
173	(-x '/usr/lib/sendmail' and '/usr/lib/sendmail') ||
174	'';
175#	'~_~sendmail~_~';
176
177#select a DBM
178
179BEGIN {
180	$Global::GDBM = $Global::DB_File = $Global::SDBM =
181# LDAP
182	$Global::LDAP =
183# END LDAP
184# SQL
185	$Global::DBI =
186# END SQL
187    $Global::Shadow =
188	0;
189
190# SQL
191	# This is for standard DBI
192	eval {
193			die if $ENV{MINIVEND_NODBI};
194			require DBI and $Global::DBI = 1
195	};
196# END SQL
197# LDAP
198	eval {
199		die if $ENV{MINIVEND_NOLDAP};
200		require Net::LDAP and $Global::LDAP = 1
201	};
202# END LDAP
203
204	# Now can use any type of database
205	AUTO: {
206		last AUTO if
207			(defined $ENV{MINIVEND_DBFILE} and $Global::DB_File = 1);
208		last AUTO if
209			(defined $ENV{MINIVEND_SDBM} and $Global::SDBM = 1);
210		last AUTO if
211			(defined $ENV{MINIVEND_NODBM});
212		eval {require GDBM_File and $Global::GDBM = 1};
213		last AUTO if
214			(defined $ENV{MINIVEND_GDBM} and $Global::GDBM = 1);
215		last AUTO if
216				!   $ENV{MINIVEND_ALLDBM}
217				and $Global::GDBM;
218		eval {require DB_File and $Global::DB_File = 1};
219		last AUTO if
220				!   $ENV{MINIVEND_ALLDBM}
221				and $Global::GDBM || $Global::DB_File;
222		eval {require SDBM_File and $Global::SDBM = 1};
223	}
224
225	if($Global::GDBM) {
226		require Vend::Table::GDBM;
227		import GDBM_File;
228		$Global::GDBM = 1;
229		$Global::Default_database = 'GDBM'
230			unless defined $Global::Default_database;
231	}
232	if($Global::DB_File) {
233		require Vend::Table::DB_File;
234		import DB_File;
235		$Global::DB_File = 1;
236		$Global::Default_database = 'DB_FILE'
237			unless defined $Global::Default_database;
238	}
239	if($Global::SDBM) {
240		require Vend::Table::SDBM;
241		import SDBM_File;
242		$Global::SDBM = 1;
243		$Global::Default_database = 'SDBM'
244			unless defined $Global::Default_database;
245	}
246	$Global::Default_database = 'MEMORY'
247			unless defined $Global::Default_database;
248	require Vend::Table::InMemory;
249	require Vend::Table::Shadow;
250}
251
252
253use Vend::Util;
254use Vend::File;
255use Vend::Server;
256use Vend::Session;
257use Vend::Config;
258use Vend::Payment;
259use Vend::Ship;
260
261# You might try commenting out these lines and uncommenting the ones
262# below to compact memory size
263# NOAUTOUSE
264use Vend::Order;
265#use Vend::Imagemap;
266#use Vend::Error;
267#use Vend::Control;
268# END NOAUTOUSE
269
270
271# You might try commenting out these lines and uncommenting the ones
272# below to do development or test for strange problems
273# AUTOUSE
274use autouse 'Vend::Error' => qw/get_locale_message interaction_error do_lockout full_dump/;
275use autouse 'Vend::Imagemap' => qw/action_map/;
276use autouse 'Vend::Control' => qw/
277											signal_reconfig
278											signal_add
279											signal_jobs
280											signal_remove
281											control_interchange
282											remove_catalog
283											add_catalog
284											change_catalog_directive
285											change_global_directive
286									/;
287#use autouse 'Vend::Order' => qw/
288#											add_items
289#											check_order
290#											check_required
291#   										encrypt_standard_cc
292#   										mail_order
293#   										onfly
294#   										route_order
295#   										validate_whole_cc
296#   								/;
297
298# END AUTOUSE
299
300use Vend::Scan;
301use Vend::Data;
302use Vend::UserDB;
303use Vend::Interpolate;
304use Vend::Page;
305use Vend::CounterFile;
306use Vend::Dispatch;
307
308if($ENV{INTERCHANGE_REQUIRE}) {
309	my @mods = split /[;\s]+/, $ENV{INTERCHANGE_REQUIRE};
310	foreach my $mod (@mods) {
311		eval {
312			eval "require $mod";
313			die $@ if $@;
314		};
315		if($@) {
316			die errmsg(
317				"FAILED to require module %s as specified in environment. Error: %s\n",
318				$mod,
319				$@,
320			);
321		}
322		else {
323			warn errmsg(
324				"Required module %s successfully as specified in environment.\n",
325				$mod,
326			);
327		}
328	}
329}
330
331if( ! $Global::Windows and $> == -1 || scalar(getpwuid($>)) eq 'nobody' ) {
332	warn errmsg("\aYou probably don't want to run as nobody!\n");
333	sleep 1;
334	warn errmsg("The security problems are on your head, though. Continuing...\n");
335}
336
337## This was set to 1 in Vend::Config, so that external programs calling it
338## would act properly by default
339undef $Vend::ExternalProgram;
340
341## DEBUG
342
343sub dontwarn {
344
345	$Global::Shadow +
346	$Vend::JobsJob +
347	$Vend::Interpolate::MAIL +
348	$Vend::Server::RUNDIR +
349
350	1;
351}
352
353sub version {
354	print "Interchange version $VERSION copyright 2002-2010 Interchange Development Group and others.\n";
355}
356
357=head1 NAME
358
359interchange - an e-commerce and general HTTP database display system
360
361=head1 SYNOPSIS
362
363interchange [--options] [file]
364
365=head1 VERSION
366
3675.6.3
368
369=head1 DESCRIPTION
370
371Interchange is a database access and retrieval system focused on e-commerce.
372It allows customers to select items to buy from catalog pages. The program
373tracks user information in sessions and interacts with an HTTP server
374through sockets.
375
376Interchange has many, many, functions and features; they are too numerous
377to describe in this venue. Complete information can be found at
378its web site:
379
380		http://www.icdevgroup.org/
381
382Interchange requires Perl 5.8.0 or higher; more information on Perl can
383be seen at:
384
385		http://www.perl.com/
386
387=head1 OPTIONS
388
389Interchange uses the Getopt::Long module, and most options will be recognized
390if they uniquely identifiable. The canonical forms are:
391
392=over 4
393
394=item -a, --add
395
396Add a catalog to the system. Information taken from the input file
397(or standard input). Implies reconfig=catalog. Example:
398
399  echo "Catalog simple /catalogs/simple /simple.cgi" | bin/interchange -a
400
401The information is in the form of a standard Interchange catalog line,
402and must be in the single-line format.
403
404=item --runjobs=catalog[=job]
405
406Run a jobs group which is a series of files in a directory with
407the name corresponding to the C<job>. For instance, if you
408set up a directory called "weekly" in your pages directory
409for the catalog C<foundation>, you can run those files with:
410
411	interchange --runjobs=foundation=weekly
412
413Files ending in .html (or whatever HTMLsuffix is for that catalog)
414are skipped. It is not tree-recursive -- directories are ignored.
415
416Results can be emailed to an address if you specify --email=address,
417and they will be put in the jobs log file.
418
419Alternatively jobs can be specified with --jobgroup=jobname B<before>
420the --runjobs option. In other words, this will work:
421
422	interchange --jobgroup=weekly --runjobs=foundation
423
424This will NOT work:
425
426	interchange --runjobs=foundation --jobgroup=weekly
427
428=item -d dir, --dir=dir
429
430Directory for VendRoot. This is where the Interchange configuration file
431will be looked for (if not redefined with C<-f>), and where the log file
432will go (if not redefined with the ErrorFile directive).
433
434=item -e name, --exclude=name
435
436Exclude catalog from this startup.
437
438=item -email=address
439
440Email address to email jobs results to.
441
442=item -f file, --config=file
443
444Configuration file to use (default is interchange.cfg in VendRoot).
445
446=item -h, --help
447
448Display help on command line options.
449
450=item -i, --inetmode
451
452Run with internet-domain socket only. Normally Interchange runs with
453both UNIX- and internet-domain sockets (except on Windows).
454
455=item --jobgroup=job
456
457Sets the job for --runjobs if that is not included in the --runjobs
458call. MUST precede the --runjobs entry on the command line.
459
460	interchange --jobgroup=weekly --runjobs=foundation
461
462See --runjobs for an explanation of what this does.
463
464=item --kill [signal]
465
466By default, kills the server ungracefully with signal KILL (9, usually).
467The optional signal will be sent instead if supplied.
468
469=item -q, --quiet
470
471Suppress informational messages on startup. Only errors are shown.
472
473=item --reconfig=name
474
475Cause only catalog C<name> to re-read its configuration.
476
477=item --remove=catalog
478
479Remove a catalog from operation; any future requests will get a not-found
480message.
481
482=item -r, --restart
483
484Stop and restart the server. This may take a long time if many catalogs
485are in use, and will temporarily take the system offline. If you want to
486change a UserTag, use the --add option instead.
487
488=item --serve
489
490This is the default if no mode options (--reconfig, --kill, --restart, etc.)
491are supplied.
492
493=item --stop
494
495Stop server gracefully with a TERM signal.
496
497=item -t, --test
498
499Report problems with config files; causes a complete configuration of
500the Interchange server but no server start.
501
502=item -u, --unix
503
504Run with unix-domain socket only. Normally Interchange runs with
505both UNIX- and internet-domain sockets. This will not work on Windows.
506
507=item -v, --version
508
509Display program version.
510
511=item --DEBUG=1
512
513Set to true value to run foreground in debug mode. It is normal to
514receive warnings about various things if you run with perl -w.
515
516=cut
517
518=item Directive=value
519
520Set a Interchange global directive upon start (or --restart). Example:
521
522	interchange SocketPerms=0666
523
524This will start the server and override the default of SocketPerms or the
525value set in interchange.cfg for this instance only. Any --restarts must
526re-specify the directive if it is still to have that value.
527
528=item name:Directive=value
529
530Set a Interchange directive for catalog C<name> upon start (or --restart). Example:
531
532	interchange simple:VendURL="http://localhost/cgi-bin/simple"
533
534This will start the server and override the default of VendURL for the
535value set in catalog.cfg for this instance only. Any --restarts must
536re-specify the directive if it is still to have that value.
537
538=back
539
540=cut
541
542sub usage {
543	version();
544	print <<'END';
545
546Interchange comes with ABSOLUTELY NO WARRANTY.  This is free software, and
547you are welcome to redistribute and modify it under the terms of the
548GNU General Public License.
549
550Command line options (first letter will usually work):
551
552     --add=catalog         add a catalog to operation; parms taken from the
553                           standard input as a "Catalog ..." directive
554     -d dir, --dir=dir     directory for VendRoot (interchange.cfg, error.log, etc.)
555     -e name,
556        --exclude=name     exclude catalog
557     --email=emailaddr     Send results of cron job to emailaddr
558     -f file,
559        --config=file      configuration file (default interchange.cfg)
560     --files spec          filespec (perl regexp OK) for static page tree
561     -h, --help            display this message
562     -i, --inetmode        run with Internet-domain socket (TCP)
563     --jobgroup=jobname    job group to run (hourly, daily, weekly, etc.)
564     --kill [signal]       kill server ungracefully (9 or with optional signal)
565     -q, --quiet           suppress informational messages on startup
566     --reconfig=catalog    reconfig a particular catalog on the server
567     --remove=catalog      remove a catalog from operation
568     -r, --restart         restart server
569     --runjobs=catalog[=job]  run jobs for a particular catalog
570                           (can use --jobgroup and -email)
571     --serve               start server (default) (-start is alias)
572     --stop                stop server gracefully
573     -t, --test            report problems with config files
574     -u, --unix            run with UNIX-domain socket
575     -v, --version         display program version
576     --DEBUG=1             run foreground in debug mode
577END
578}
579
580## MAIN
581
582sub catch_warnings {
583	unless($_[0]) {
584		$SIG{'__WARN__'} = '';
585		return;
586	}
587	$SIG{'__WARN__'} = sub {
588		return @_ unless $_[0] =~ /^Use of uninitialized /;
589		my $warn = $_[0];
590		my $configline;
591		if($warn =~ /CONFIG>\s+chunk\s+(\d+)/) {
592			return <<EOF;
593There is a possible problem in this catalog at line $configline
594of the catalog.cfg file. Please check it out.
595EOF
596		}
597		return @_;
598	};
599}
600
601sub parse_options {
602
603	use Getopt::Long;
604
605	Getopt::Long::config(qw/permute/);
606
607	#Getopt::Long::config(qw/debug/);
608	my $rcfgsub = sub {
609						my ($mode, $val) = @_;
610						die "Can't set two modes -$mode and -$Vend::mode.\n"
611								if $Vend::saw_mode;
612						$Vend::Quiet = 1
613							unless defined $Vend::Quiet;
614						$Vend::saw_mode = 1;
615						push @Vend::CatalogToReconfig, $val;
616						$Vend::mode = $mode;
617					};
618	my $modesub = sub {
619						my ($mode, $val) = @_;
620						die "Can't set two modes -$mode and -$Vend::mode.\n"
621								if $Vend::saw_mode;
622						$Vend::saw_mode = 1;
623						$Vend::mode = $mode;
624					};
625
626	my ($c_direc, $g_direc);
627
628	my @args = @ARGV;
629	my $ignore = 0;
630
631	my %optctl = (
632
633		DEBUG 		    => \$Global::DEBUG,
634		reconfig        => $rcfgsub,
635		confdir         => \$Global::ConfDir,
636		rundir          => \$Global::RunDir,
637		configfile      => \$Global::ConfigFile,
638		dir          	=> \$Global::VendRoot,
639		exclude         => \%Vend::CatalogToSkip,
640		help            => sub { usage(); exit 0 },
641		inetmode        => \$Global::Inet_Mode,
642		log             => \$Global::ErrorFile,
643		quiet			=> \$Vend::Quiet,
644		pidfile			=> \$Global::PIDfile,
645		soappidfile		=> \$Global::SOAP_PIDfile,
646		serve           => $modesub,
647
648		test			=> $modesub,
649		globalconfig	=> sub { $Vend::Quiet = 1; $modesub->('globalconfig') },
650		unixmode        => \$Global::Unix_Mode,
651		version         => sub { version(); exit 0 },
652		stop			=> \&control_interchange,
653		add				=> \&signal_add,
654		email 			=> \$Vend::JobsEmail,
655		flag			=> \$Vend::JobsFlag,
656		jobgroup		=> \$Vend::JobsJob,
657		runjobs			=> \&signal_jobs,
658		remove			=> \&signal_remove,
659		kill			=> \&control_interchange,
660		Ignore 			=> \$ignore,
661		restart			=> sub {
662								return if $ignore;
663								$ignore = 1;
664								control_interchange('stop', 'TERM', 1);
665								sleep 3;
666								exec $0, '--Ignore', @args;
667							},
668		'<>'			=> sub {
669							my ($arg) = @_;
670							return unless $arg =~ /=/;
671							my ($opt, $val) = split /=/, $arg, 2;
672							my $cat;
673							if($opt =~ /:/) {
674								($cat, $opt) = split /:/, $opt, 2;
675							}
676
677							my $direc;
678							if($cat) {
679								$c_direc = Vend::Config::catalog_directives()
680									unless $c_direc;
681								$direc = $c_direc;
682							}
683							else {
684								$g_direc = Vend::Config::global_directives()
685									unless $g_direc;
686								$direc = $g_direc;
687								$cat = 'mv_global';
688							}
689							my $found;
690
691							for (@$direc) {
692								next unless (lc $opt) eq (lc $_->[0]);
693								$found = $_->[0];
694								last;
695							}
696							unless ($found) {
697								warn "Unrecognized directive '$arg', skipping.\n";
698								return;
699							}
700
701							$MV::Default{$cat} = {},
702							$MV::DefaultAry{$cat} = []
703								unless $MV::Default{$cat};
704							$MV::Default{$cat}{$found} = $val
705								unless defined $MV::Default{$cat}{$found};
706							push @{$MV::DefaultAry{$cat}}, "$found $val";
707							return;
708							},
709	);
710
711	my @options = ( qw/
712		DEBUG:i
713		Ignore
714		add|a=s
715        confdir=s
716        configfile|config|c|f=s
717        dir|vendroot|d=s
718        email=s
719        exclude|e=s
720        flag=i
721		help|h
722		globalconfig
723        inetmode|inet|i
724        jobgroup=s
725        kill:s
726        log|logfile|l=s
727        quiet|q
728        rundir=s
729		runjobs=s
730		pidfile=s
731		reconfig=s
732		remove=s
733		restart|r
734		serve|start|s
735		stop:s
736		test|t
737		unixmode|unix
738		version|v
739		<>
740	/ );
741
742	GetOptions(\%optctl, @options);
743
744}
745
746# This routine is called at startup. It performs the program and
747# catalog configuration functions, to wit:
748#
749#   --- seed random generator
750#   --- set up a couple of preloaded arrays
751#   --- parse command-line options
752#   --- read global configuration file interchange.cfg and
753#       get catalog definitions
754#   --- configure each catalog and store its configuration
755#       in a reference mapped to the SCRIPT_NAME or catalog name
756#   --- determine the program mode, and if it is to begin daemon
757#       operation, run the Vend::Server::run_server() routine.
758#   --- If Vend::Server::run_server() is entered, that will
759#       never exit until a signal is sent
760#
761sub main_loop {
762	# Setup
763	unless ($Global::Windows) {
764		$ENV{'PATH'} = '/bin:/usr/bin';
765		$ENV{'SHELL'} = '/bin/sh';
766		$ENV{'IFS'} = '';
767	}
768	# Initially seed the random generator
769	srand;
770
771	# Set up a couple of arrays
772	setup_escape_chars();
773
774	# These are only starting values, can be changed by command-line
775	# options or the interchange.cfg file
776	$Global::ConfDir = "$Global::VendRoot/etc";
777	$Global::RunDir = "$Global::VendRoot/etc";
778	$Global::PIDfile = "$Global::RunDir/$Global::ExeName.pid";
779	$Global::SOAP_PIDfile = "$Global::RunDir/$Global::ExeName.soap.pid";
780
781	$Vend::mode = 'serve';      # mode will be reset by options if appropriate
782
783	# Parse command line options, getting mode if not -serve
784	# May actually exit in some situations
785	parse_options()
786		or usage(), die "\n";
787
788	# Cannot run as root unless in 'make test'
789	if($> == 0 and ! $Global::Windows) {
790		die errmsg("The Interchange server must not be run as root.\n")
791			unless $ENV{MINIVEND_ROOT} =~ m{/blib$};
792	}
793
794# LEGACY
795	# Kept here for compatibility
796	eval {
797		require Vend::Payment::CyberCash;
798	};
799# END LEGACY
800
801	# These modules no longer necessary, why take up memory?
802	delete $INC{'Getopt/Long.pm'};
803
804	$Global::ErrorFile = "$Global::VendRoot/error.log"
805		if $Global::ErrorFile eq $Global::InitialErrorFile;
806	undef $Global::InitialErrorFile;
807
808	chdir($Global::VendRoot)
809		or die "Couldn't change directory to $Global::VendRoot: $!\n";
810	$Global::ConfigFile = "$Global::VendRoot/$Global::ExeName.cfg"
811		if ! $Global::ConfigFile;
812
813	die "Interchange not configured, no $Global::ConfigFile.\n"
814		unless -f $Global::ConfigFile;
815
816	if(! $Global::DEBUG) {
817		$Global::DEBUG = $ENV{MINIVEND_DEBUG} || 0;
818	}
819
820print errmsg("\n##### DEBUG MODE, running in foreground #####\n") if $Global::DEBUG;
821
822	# Restrictive file permissions to begin with
823	umask 077;
824
825	# Read interchange.cfg (or whatever its name is set to be)
826	global_config();
827
828	if($Vend::mode eq 'globalconfig') {
829		print Vend::Util::uneval($Global::Structure);
830		exit;
831	}
832	# Select locking mode
833	set_lock_type();
834
835	Vend::Dispatch::update_global_actions();
836
837#::logDebug(::uneval(\%Global::Catalog));
838
839	# This is only gotten to if -reconfig passed in on command line
840	if($Vend::mode eq 'reconfig') {
841		eval {
842			signal_reconfig(@Vend::CatalogToReconfig);
843		};
844		die "$@\n" if $@;
845		exit;
846	}
847
848	logGlobal( "Interchange V$VERSION");
849
850	SIGNALCHECK: {
851		my $high_enough;
852		eval {
853			require 5.8.2;
854			$high_enough = 1;
855		};
856		last SIGNALCHECK unless $high_enough;
857		if($ENV{PERL_SIGNALS} and $ENV{PERL_SIGNALS} eq 'unsafe') {
858			logGlobal("Running with old signals.");
859		}
860		else {
861			my $msg = <<EOF;
862Running with new signals, external programs could be unreliable.
863Re-run with environment variable PERL_SIGNALS set to "unsafe" to change this.
864EOF
865			chomp $msg;
866			logGlobal($msg);
867		}
868	}
869
870	THREADCHECK: {
871		last THREADCHECK unless $Global::TryingThreads;
872		$] >= 5.008_008 and last THREADCHECK;
873
874		my $msg = <<EOF;
875***************************************************************
876***************************************************************
877****                                                       ****
878****  You are running a Perl with threads enabled -- this  ****
879****  is not recommended for a production environment.     ****
880****                                                       ****
881****  If the Interchange daemon does not start, add this   ****
882****  line to interchange.cfg:                             ****
883****                                                       ****
884****    Variable MV_GETPPID_BROKEN  1                      ****
885****                                                       ****
886****  Then restart the server.                             ****
887****                                                       ****
888***************************************************************
889***************************************************************
890EOF
891		chomp $msg;
892		logGlobal($msg);
893	}
894
895	# The global configuration set up which catalogs exist.
896	# Certain ones may have been skipped with -skip on command line...
897	CATCONFIG: {
898		my $i = 0;
899		my ($g, $c, $name);
900		foreach $name (sort keys %Global::Catalog) {
901			$g =  $Global::Catalog{$name};
902			next if defined $Vend::CatalogToSkip{$g->{'name'}};
903			print "Configuring catalog " . $g->{'name'} . '...'
904				unless $Vend::Quiet or $g->{name} eq '_mv_admin';
905			if (exists $Global::Selector{$g->{'script'}}) {
906				warn "Two catalogs with same script name $g->{'script'}.\n";
907				warn "Skipping catalog $g->{'name'}....\n\n";
908				next;
909			}
910
911			# Set WARN handler to atch certain warnings and maybe elucidate
912			catch_warnings(1);
913
914			# This actually configures the catalog
915			eval {
916				$c = config_named_catalog($name, "at server startup");
917			};
918
919			# See if catalog configuration erred in some way....
920			if ($@ or ! defined $c) {
921				my $msg = $@;
922				print "\n$msg\n\a$g->{'name'}: error in configuration. Skipping.\n";
923				$msg =~ s/\s+$//;
924				$msg = " -- $msg" if $msg;
925				logGlobal $g->{'name'} . ": config error$msg. Skipping.";
926				undef $Global::Selector{$g->{'script'}};
927				next;
928			}
929
930			# Reset WARN handler
931			catch_warnings(0);
932
933			# Set up the mapping of the main SCRIPT_NAME
934			$Global::Selector{$g->{script}} = $c;
935
936			# Set up aliases
937			if (defined $g->{alias}) {
938				for(@{$g->{alias}}) {
939					if (exists $Global::Selector{$_}) {
940						warn "Alias $_ used a second time, skipping.\n";
941						next;
942					}
943					elsif (m![^-\w_:~#/.]!) {
944						warn "Bad alias $_, skipping.\n";
945					}
946					$Global::Selector{$_} = $c;
947					$Global::SelectorAlias{$_} = $g->{'script'};
948				}
949			}
950
951			print "done.\n"  unless $Vend::Quiet or $g->{name} =~ /^_/;
952		}
953	}
954
955	#undef $Global::DumpStructure;
956
957	if ($Vend::mode eq 'serve') {
958		undef $Global::Foreground;
959
960		# Here we prepare enter the daemon mode.
961
962		# Set $0 to something pretty for ps(1).
963		# This is all done in Vend::Server::set_process_name now.
964		Vend::Server::set_process_name($Global::VendRoot);
965
966		# This should never return unless killed or a catastrophic error
967		Vend::Server::run_server();
968	}
969	elsif($Vend::mode eq 'test') {
970		# Blank by design, this option only tests config files
971		# or builds catalogs
972	}
973	else {
974		die "No mode!\n";
975	}
976
977}
978
979### This is where we run after the first portion of the initialization
980eval { main_loop(); };
981if ($@) {
982	my($msg) = ($@);
983	$Vend::Log_suppress = 1;
984	logGlobal( $msg );
985	if ($Global::DisplayErrors) {
986		print "$msg\n";
987	}
988	die "$msg\n" if $Global::Foreground;
989}
990
991=head1 SEE ALSO
992
993compile_link(1), config_prog(1), configdump(1), dump(1), expire(1),
994expireall(1), localize(1), makecat(1), offline(1), restart(1), update(1),
995http://www.icdevgroup.org/
996
997=head1 LICENSE
998
999Interchange comes with ABSOLUTELY NO WARRANTY. This is free software, and
1000you are welcome to redistribute and modify it under the terms of the
1001GNU General Public License.
1002
1003=head1 COPYRIGHT
1004
1005    Copyright (C) 2002-2010 Interchange Development Group
1006    Copyright (C) 1995-2002 Red Hat, Inc.
1007    All rights reserved except those granted in the license.
1008
1009=cut
1010
1011=head1 AUTHOR
1012
1013Mike Heins is the primary author of Interchange.
1014
1015The Interchange Development Group is:
1016
1017Dan Browning
1018David Kelly
1019Davor Ocelic
1020Ethan Rowe
1021Gert van der Spoel
1022Greg Hanson
1023Jon Jensen
1024Jonathan Clark
1025Kevin Walsh
1026Mark Johnson
1027Mike Heins
1028Paul Vinciguerra
1029Peter Ajamian
1030Stefan Hornburg (aka Racke), captain
1031Randy Moore
1032Ron Phipps
1033Ton Verhagen
1034
1035Please do not contact the authors directly for help with the system.
1036Use the Interchange mail list:
1037
1038    interchange-users@icdevgroup.org
1039
1040Information on subscribing to the list, as well as general information and
1041documentation for Interchange is at:
1042
1043    http://www.icdevgroup.org/
1044
1045=head1 ACKNOWLEDGEMENTS
1046
1047Original author of Vend, ancestor to Minivend and Interchange, was
1048Andrew Wilcox <amw@wilcoxsolutions.com>. Interchange could never have
1049come into being without him. Interchange was based on Vend 0.2, with
1050portions from Vend 0.3; both were produced in 1995.
1051
1052Contributions to Interchange have been made by:
1053
1054=cut
1055
1056# columnize with "sort -u | pr -t -2 | expand -8 | sed 's/^/    /'"
1057
1058=pod
1059
1060    Andreas Koenig           Jason Holt
1061    Bill Carr                Jason Kohles
1062    Bill Dawkins             Javier Martin
1063    Bill Randle              Jeff Carnahan
1064    Birgitt Funk             Jeff Nappi
1065    Bob Jordan               Jochen Wiedmann
1066    Brev Patterson           Jos� M� Revuelto
1067    Brian Bullen             Jure Kodzoman
1068    Brian Kosick             Jurgen Botz
1069    Bruce Albrecht           Keiko
1070    Cameron Prince           Keith Oberlin
1071    Chen Naor                Kim Lauritz Christensen
1072    Christian Mueller        Larry Leszczynski
1073    Christopher Miller       Marc Austin
1074    Christopher Thompson     Mark Stosberg
1075    Dan Busarow              Massimiliano Ciancio
1076    Dan Helfman              Matthew Schick
1077    Daniel Thompson          Michael McCune
1078    Dave Wingate             Michael Wilk
1079    David Adams              Mike Frager
1080    Dennis Cronin            Neil Evans
1081    Don Grodecki             Nelson Ferrari
1082    Ed LaFrance              Raj Goel
1083    Frank Bonita             Ray Desjardins
1084    Frederic Steinfels       Shozo Murahashi
1085    Gunnar Hellekson         Sonny Cook
1086    Hamish Bradick           Tim Baverstock
1087    Hans-Joachim Leidinger   Tom Friedel
1088    Heinz Wittenbecher       Tommi Laberno
1089    Hiroyuki Cozy Kojima     Troy Davis
1090    Ignacio Lizar�n          Victor Nolton
1091    Jack Tsai                William Dan Terry
1092    and many others
1093
1094and, of course, the entire Perl team without whom Interchange could not exist.
1095
1096=cut
1097
1098$Global::mod_perl ? 1 : 0;
1099
1100__END__
1101