#!/usr/bin/perl
# (c) Copyright 2001-2018. CodeWeavers, Inc.
use warnings;
use strict;
my $ldpath_envname="LD_LIBRARY_PATH";
# Portable which(1) implementation
sub cxwhich($$;$)
{
my ($dirs, $app, $noexec)=@_;
if ($app =~ /^\//)
{
return $app if ((-x $app or $noexec) and -f $app);
}
elsif ($app =~ /\//)
{
require Cwd;
my $path=Cwd::cwd() . "/$app";
return $path if ((-x $path or $noexec) and -f $path);
}
else
{
foreach my $dir (split /:/, $dirs)
{
return "$dir/$app" if ($dir ne "" and (-x "$dir/$app" or $noexec) and -f "$dir/$app");
}
}
return undef;
}
# Fast dirname() implementation
sub _cxdirname($)
{
my ($path)=@_;
return undef if (!defined $path);
return "." if ($path !~ s!/+[^/]+/*$!!s);
return "/" if ($path eq "");
return $path;
}
# Locate where CrossOver is installed by looking for the directory
# where the cxmenu script is located, unwinding symlinks on the way
sub locate_cx_root(;$)
{
my ($fallback)=@_;
my $argv0=cxwhich($ENV{PATH},$0);
$argv0=$0 if (!defined $argv0);
if ($argv0 !~ m+^/+)
{
require Cwd;
$argv0=Cwd::cwd() . "/$argv0";
}
my $dir=_cxdirname($argv0);
my $bindir=$dir;
$bindir =~ s%/lib$%/bin%;
while (!-x "$bindir/cxmenu" or !-f "$bindir/cxmenu")
{
last if (!-l $argv0);
$argv0=readlink($argv0);
$argv0="$dir/$argv0" if ($argv0 !~ m+^/+);
$dir=_cxdirname($argv0);
$bindir=$dir;
$bindir =~ s%/lib$%/bin%;
}
$bindir =~ s%/(?:\./)+%/%g;
$bindir =~ s%/\.$%%;
$ENV{CX_ROOT}=_cxdirname($bindir);
if ((!-x "$ENV{CX_ROOT}/bin/cxmenu" or !-f "$ENV{CX_ROOT}/bin/cxmenu") and
$fallback)
{
$ENV{CX_ROOT}=$fallback;
}
if (!-x "$ENV{CX_ROOT}/bin/cxmenu" or !-f "$ENV{CX_ROOT}/bin/cxmenu")
{
my $name0=$0;
$name0 =~ s+^.*/++;
print STDERR "$name0:error: could not find CrossOver in '$ENV{CX_ROOT}'\n";
exit 1;
}
return $ENV{CX_ROOT};
}
BEGIN {
unshift @INC, locate_cx_root() . "/lib/perl";
}
use CXLog;
use CXUtils;
# Process command-line options
my $opt_bottle;
my $opt_scope;
my $arg_app;
my $opt_update_only;
my $ux_app;
my $cx_app;
my $wl_app;
my $wl32_app;
my $cx_hooks;
my $opt_start;
my $opt_start_only;
my $opt_start_default;
my $opt_start_mime;
my $opt_start_class;
my $opt_start_verb;
my $opt_wait_all;
my $opt_check; # For backward compatibility
my $opt_desktop;
my $opt_workdir;
my $opt_convert;
my $opt_quotes;
my $opt_lock;
my $opt_update;
my $opt_display;
my $opt_gui=1;
my $opt_new_console;
my $opt_allow_root;# For backward compatibility
my $opt_wait;
my $opt_wait_children;
my $opt_untrusted;
my $opt_verbose=1 if (CXLog::is_on());
my $opt_cx_log;
my $opt_debugmsg=$ENV{CX_DEBUGMSG};
my $opt_dlloverrides;
my $opt_dashdash;
my $opt_winver;
my $opt_version;
my $opt_help;
my $opt_demo_status;
my $opt_demo_nag;
my $opt_enable_alt_loader;
require CXOpts;
my $cxopts=CXOpts->new(["stop_on_unknown","stop_on_non_option"]);
$cxopts->add_options(["bottle=s" => \$opt_bottle,
"scope=s" => \$opt_scope,
"update-only" => \$opt_update_only,
"ux-app=s" => \$ux_app,
"cx-app=s" => \$cx_app,
"wl-app=s" => \$wl_app,
"wl32-app=s" => \$wl32_app,
"cx-hooks=s" => \$cx_hooks,
"start=s" => \$opt_start,
"start-only=s" => \$opt_start_only,
"start-default=s" => \$opt_start_default,
"start-mime=s" => \$opt_start_mime,
"start-class=s" => \$opt_start_class,
"start-verb=s" => \$opt_start_verb,
"desktop=s" => \$opt_desktop,
"workdir=s" => \$opt_workdir,
"convert!" => \$opt_convert,
"quotes!" => \$opt_quotes,
"lock!" => \$opt_lock,
"update!" => \$opt_update,
"check" => \$opt_check,
"allow-root!" => \$opt_allow_root,
"untrusted!" => \$opt_untrusted,
"debugmsg=s" => \$opt_debugmsg,
"dll=s" => \$opt_dlloverrides,
"winver=s" => \$opt_winver,
"wait!" => \$opt_wait,
"wait-children" => \$opt_wait_children,
"wait-all" => \$opt_wait_all,
"display=s" => \$opt_display,
"gui!" => \$opt_gui,
"new-console" => \$opt_new_console,
"verbose!" => \$opt_verbose,
"cx-log=s" => \$opt_cx_log,
"" => \$opt_dashdash,
"version" => \$opt_version,
"demo-status" => \$opt_demo_status,
"demo-nag" => \$opt_demo_nag,
"enable-alt-loader=s" => \$opt_enable_alt_loader,
"?|h|help" => \$opt_help
]);
my $err=$cxopts->parse();
if ($opt_verbose)
{
CXLog::fdopen(2);
$opt_cx_log="-" if (!defined $opt_cx_log);
}
my $default_warning;
if (!defined $opt_bottle and !defined $ENV{CX_BOTTLE})
{
$default_warning="";
$opt_bottle="default";
}
$ENV{CX_BOTTLE}=$opt_bottle if (defined $opt_bottle);
# Validate the command line options
my $usage;
if ($err)
{
cxerr("$err\n");
$usage=2;
}
elsif ($opt_help)
{
$usage=0;
}
elsif ($opt_version)
{
$usage=3;
}
else
{
if (cxname0() eq "cxstart")
{
if (defined $opt_start)
{
cxerr("--start cannot be used with cxstart\n");
$usage=2;
}
elsif (!@ARGV)
{
cxerr("you must specify the document to open with cxstart\n");
$usage=2;
}
else
{
$opt_start=shift @ARGV;
}
}
if (!defined $opt_cx_log)
{
$opt_cx_log = "-";
$opt_debugmsg="-all" if (!defined $opt_debugmsg);
}
elsif ($opt_cx_log eq "/dev/null" and !defined $ux_app)
{
# No point sending traces to /dev/null
$opt_debugmsg = "-all";
}
$ENV{DISPLAY}=$opt_display if (defined $opt_display);
$ENV{CX_DEBUGMSG}=$opt_debugmsg if (defined $opt_debugmsg);
my $cmd_count=0;
$cmd_count++ if (defined $opt_update_only);
$cmd_count++ if (defined $ux_app);
$cmd_count++ if (defined $cx_app);
$cmd_count++ if (defined $wl_app);
$cmd_count++ if (defined $wl32_app);
$cmd_count++ if (defined $cx_hooks);
$cmd_count++ if (defined $opt_start);
$cmd_count++ if (defined $opt_wait_all);
$cmd_count++ if (defined $opt_demo_status);
$cmd_count++ if (defined $opt_demo_nag);
if ((@ARGV or $cmd_count > 1) and ($opt_demo_status or $opt_demo_nag))
{
cxerr("--demo-status and --demo-nag must be used alone\n");
$usage=2;
}
elsif ($cmd_count>1)
{
cxerr("--cx-app, --ux-app, --wl-app, --wl32-app, --cx-hooks, --start, --wait-all and --update-only are mutually exclusive\n");
$usage=2;
}
elsif ($cmd_count == 0)
{
if (cxname0() ne "wine")
{
$arg_app=cxname0();
}
else
{
if (!@ARGV)
{
cxerr("you must specify an application to run\n");
$usage=2;
}
elsif (!$opt_dashdash and @ARGV > 1 and $ARGV[1] eq "--")
{
splice @ARGV, 1, 1;
}
}
}
if (!defined $opt_wait)
{
$opt_wait=1;
}
elsif (defined $opt_wait_children)
{
cxerr("--wait and --wait-children are mutually incompatible\n");
$usage=2;
}
if (defined $opt_start)
{
my $start_count=0;
$start_count++ if (defined $opt_start_default);
$start_count++ if (defined $opt_start_mime);
$start_count++ if (defined $opt_start_class);
if ($start_count > 1)
{
cxerr("--start-default, --start-mime and --start-class are mutually incompatible\n");
$usage=2;
}
}
elsif (defined $opt_start_only or defined $opt_start_default or
defined $opt_start_mime or defined $opt_start_class or
defined $opt_start_verb)
{
cxerr("--start-only, --start-default, --start-mime, --start-class and --start-verb can only be used with --start\n");
$usage=2;
}
if (defined $opt_scope)
{
$opt_scope=~ tr/A-Z/a-z/ ;
if ($opt_scope !~ /^(?:managed|private)$/)
{
cxerr("unknown scope value '$opt_scope'\n");
$usage=2;
}
}
if (defined $ux_app or defined $cx_hooks)
{
if (defined $opt_convert or defined $opt_quotes)
{
cxerr("--convert and --quotes are incompatible with --ux-app and --cx-hooks\n");
$usage=2;
}
}
else
{
$opt_convert=1 if (!defined $opt_convert);
$opt_quotes=1 if (!defined $opt_quotes);
}
$opt_lock=1 if (!defined $opt_lock);
$opt_update=1 if (!defined $opt_update and $opt_update_only);
$opt_update=1 if (!defined $opt_update and $opt_lock);
if (!$opt_update and $opt_update_only)
{
cxerr("--no-update cannot be used with --update-only\n");
$usage=2;
}
if ($opt_update and !$opt_lock)
{
cxerr("--update cannot be used with --no-lock\n");
$usage=2;
}
if ($opt_update_only and !$opt_lock)
{
cxerr("--update-only cannot be used with --no-lock\n");
$usage=2;
Loading ...