Назад | Перейти на главную страницу

CPAN использует старую версию Perl для установки модулей

Я установил Ubuntu ранее в эти выходные, и мне пришлось установить обновленную версию perl (5.22.0) для скрипта, который я использую. Однако, когда я использовал CPAN для установки необходимых мне модулей, я обнаружил, что они установлены в Perl Ubuntu по умолчанию (5.18.2). Я побежал perl -l и он показывает обновленный perl5, но по какой-то причине CPAN отказывается его использовать.

Я уверен, что это проблема конфигурации или я неправильно понимаю, как работает CPAN. В любом случае я просматривал страницы и страницы Google, пытаясь найти решение, но безрезультатно. Я надеюсь, что кто-то здесь может направить меня в правильном направлении, и, возможно, это может помочь другим, у которых есть аналогичная проблема.

У меня была точно такая же проблема. Предостережение: я использую федору. Но fc22 сломал мои сценарии perl [интерпретатор perl 5.20.3 мог выполнить segfault], поэтому мне пришлось установить 5.22.0, так что у меня есть непосредственный опыт работы с этим.


Узнаем о конфиге нового интерпретатора

Во-первых, как вы установили. Я предполагаю, что вы использовали установщик для установки двоичного пакета для 5.22.0. Это было перезаписано /usr/bin/perl? Я так полагаю. Или он был установлен как (например) /usr/bin/perl-5.22.0?

В /usr/lib64/perl/Config.pm, посмотрите внизу, чтобы найти связанный хеш. Это будет конфигурация. Другой [возможно, лучший] способ получить это - выгрузить @INC и делай use Config; и выбросить Config хеш из [конечно же - perl] скрипта.

Особый интерес будет privlibexp, sitearchexp,sitelibexp, и archlibexp переменные.

Сброс @INC является наиболее окончательным.

Вопрос, который следует отметить / ответить: использует ли интерпретатор Perl 5.22.0 каталоги 5.22.0 или часть конфигурации по-прежнему указывает на 5.18.2?

В одном или нескольких из этих каталогов должны быть CPAN.pm вместе с CPAN subdir. Я предполагаю, что ты найдешь это только в соответствующем каталоге 5.18.2.

Фактически, проведя небольшое расследование, вы можете обнаружить, что теперь у вас есть "гибридный" установка, которая не совсем 5.18.2 и не совсем 5.22.0. Если вы [решите] следовать моим "передовым рекомендациям" [см. Ниже], вы можете удалить 5.22.0, чтобы получить стандартную / стандартную установку 5.18.2. Это сводит к минимуму головную боль, если Ubuntu выпускает патч.


Немного о CPAN

Когда дистрибутив устанавливает пакеты perl, перекрывать с пакетами, которые вы можете получить из CPAN, вроде как работает. Но на самом деле они часто сталкиваются. Кроме того, использование нестандартной версии Perl против дистрибутива требует еще большей осторожности.

Возможно, вам придется установить CPAN в каталог 5.22.0 с помощью нового интерпретатора. Это может быть краткий ответ.

Итак, это поднимает вопрос о том, как вообще был установлен CPAN. Он пришел из дистрибутива или был извлечен и установлен вручную? Если из дистрибутива, «апгрейд» может сработать. В противном случае установите его вручную из нового интерпретатора perl - он должен отправить его [и все, что он устанавливает] в нужное место.

Также под $HOME ты должен найти .cpan каталог [если вы его запустили]. Особый интерес представляет $HOME/.cpan/CPAN subdir. У него должен быть файл конфигурации cpan (например, $HOME/.cpan/CPAN/MyConfig.pm). Есть ряд переменных, но make_install_make_command может быть полезно


Что я сделал - рекомендую лучшие практики

[Боковое примечание: я занимаюсь Perl более 20 лет - в моем текущем репозитории сценариев 250 000 строк].

Мне приходилось сталкиваться с подобными проблемами несколько [более чем несколько] раз. Честно говоря, я больше не «борюсь» с дистрибутивом из-за проблем вроде той, что у вас есть. Хотя на бумаге дистрибутивы Запрос чтобы иметь возможность устанавливать несколько версий пакетов одновременно, мне всегда не везло с этим, в частности с perl.

ИМО, и по моему опыту, проблема, с которой вы столкнулись, - это лишь верхушка айсберга. Даже если вы решите, возможно, позже возникнут другие похожие проблемы.

Если мне нужна альтернативная версия Perl, я захожу на сайт Perl, загружаю источник tarball и перестройте его. Примечание. Рекомендуемый совет [с веб-сайта perl] - загрузить исходный код с веб-сайта perl и не попробуйте выполнить пересборку из исходного пакета дистрибутива.

Я указываю альтернативный префикс к ./Configure сценарий, чтобы все было помещено на новое место. Затем сделайте make и make install.

Например, мой Perl 5.22.0 находится под /home/alt/perl/perl-5.22.0 и имеет bin/perl, lib/CPAN.pm, и lib/CPAN под ним. Я могу поддерживать столько разных версий, сколько хочу, потому что каждая из них /home/alt/perl/<version>

После этого я могу (например): ln -sf /home/alt/perl/perl-5.22.0/bin/perl /usr/bin/perl22 и изменить сценарии, с которыми я хочу его использовать #!/usr/bin/perl22.

Вот параметры, которые я использую для настройки Perl. Первые три являются наиболее важными [*]:

-Dprefix=/home/alt/perl/perl-5.22.0
-Dstartperl=/home/alt/perl/perl-5.22.0/bin/perl
-Dusethreads=y
-DEBUGGING=both
-Doptimize=-gdwarf-2
-Dman1dir=none
-Dcf_email=anybody@gmail.com
-Dpager=/usr/bin/less
'-Dstatic_ext=threads threads/shared'
-d
-e
-s

Обратите внимание: поскольку у меня были проблемы с Fedora 5.20.3, я, возможно, добавил некоторые дополнительные параметры отладки, которые вам не понадобятся.

Еще одно место для этого - /home/myself/perl/perl-5.22.0 если вам нужна частная / экспериментальная копия.

ПРИМЕЧАНИЕ: потому что я использовал совершенно другое место для установки 5.22.0, 5.22.0 и 5.20.3 сосуществовать в полной гармонии. Они никак не мешают [AFAICT].

Вы даже можете попробовать это без вмешиваясь в уже установленную версию 5.22.0.


Мои актуальные сценарии восстановления

[*] P.S. Конечно, у меня есть полностью автоматизированный Perl-скрипт для выполнения всей этой настройки, сборки, установки [и извлечения tarball с веб-сайта]

Эти будут не быть запущенными как есть, потому что они требуют / предполагают большую часть моей существующей инфраструктуры. Они просто для справки. Если вы хотите посмотреть на все, игнорируйте 99,44% того, что вы не сразу узнаете.

Вот скрипт для Perl:

#!/usr/bin/perl
# altbld/qprlmkx -- connect to CPAN
#
# xperl -- execute script with alternate perl interpreter
#   "-b" -- use base script name (e.g. skip XBIN)
#   "-ddd" -- run ddd on perl
#   "-db" -- run perl script debugger (perl's -d)
#   "-D" -- perl -D options (see perlrun manpage)
#   "-E" -- environment variables
#   "-Lc" -- use alternate glibc (BROKEN)
#   "-Ld" -- set up PERLIO_DEBUG
#   "-Le" -- force glibc to use stderr for fatal errors
#   "-S" -- do vxshazam (recommended for debug on vxshazam programs)
#
# pathx -- dump the path
#
# qprlmkc -- configure perl interpreter
# qprlmkx -- remake perl interpreter

use qslib::qsinit;
use qpile::qpchk;
use qsnet::rshlib;
use pjx::pjxlib;
use qpile::qploc;
use altbld::altlib;
use gtx::gtxlib;

master(@ARGV);
exit(0);

# master -- master control
sub master
{
    my(@argv) = @_;
    my($proc);
    my(@opts);

    unshift(@argv,"-ddd")
        if ($pgmtail eq "qprlgdb");

    while (1) {
        vbqdash(\@argv);
        vbqnumdcd($_,"-S",1,\$keyS);

        vbqnumdcd($_,"-go",1,\$keygo);

        if (($pgmtail eq "xperl") || ($pgmtail =~ /^tskdir/)) {
            vbqnumdcd($_,"-b",1,\$keyb);
            vbqnumdcd($_,"-db",1,\$keydb);
            vbqvstrdcd($_,"-D","tlsRSD",\@keyD);
            vbqvstrdcd($_,"-E",undef,\@keyE);

            vbqnumdcd($_,"-Le",1,\$keyLe);
            vbqnumdcd($_,"-Lc",1,\$keyLc);
            vbqnumdcd($_,"-Ld",1,\$keyLd);

            pjxdddopt($_);
            vbqnumdcd($_,"-help",1,\$keyhelp);
            vbqnumdcd($_,"-Q",1,\$keyQ);
            vbqnumdcd($_,"-S",1,\$keyS);
        }

        if ($pgmtail eq "qprlmkc") {
            vbqvstrdcd($_,"-D",undef,\@keyD);
            vbqnumdcd($_,"-publish",1,\$keypublish);
        }

        vbqnumdcd($_,"-ask",1,\$keyask);
        vbqnumdcd($_,"-sh",1,\$keysh);

        altoptdcd($_);

        sysusage($_);
    }

    vxshazam()
        if ($keyS);

    push(@opts,"-V$keyV")
        if ($keyV ne "");
    $APL = altverget(@opts,"perl");
    $ALTPERL = $APL->{alt_xfile};

    $APL->{alt_bld} = $APL->{alt_src};

    $APL->{alt_remhost} = "ftp.cpan.org";
    $APL->{alt_remtop} = "pub/CPAN/src";
    ###$APL->{alt_remdir} = "/gcc-" . $APL->{alt_revuse};
    $APL->{alt_remsuf} = ".tar.gz";

    $proc = "cmd_" . $pgmtail;
    &$proc(@argv);
}

# cmd_qprlwget -- pull perl
sub cmd_qprlwget
{

    altwget($APL);
}

# cmd_qmetacfg -- pull perl
sub cmd_qmetacfg
{
    my($sdir);
    my($tail);

    $sdir = $APL->{alt_top};
    msg("$pgmtail: chdir %s ...\n",$sdir);
    xchdir($sdir);

    # get metaconfig
    {
        if (-d $tail) {
            msg("$pgmtail: project dir already exists\n");
            last;
        }

        last;

        vxsystem("git","clone",
            "git://perl5.git.perl.org/$tail.git",
            $tail);
    }
}

# cmd_qprlver -- show versions
sub cmd_qprlver
{
}

# cmd_qprldis -- disassemble executable
sub cmd_qprldis
{

    vxsystem("-x","asmdis",$APL->{alt_xfile});
}

# cmd_qprlmkc -- configure perl
sub cmd_qprlmkc
{
    my(@opts);
    my(@shopts);
    push(@lnklist);
    my($src,$ins,$bld,$xfile);
    my($tail,$lnkto);

    $keygo = 0
        if ($keypublish);

    $src = $APL->{alt_src};
    $ins = $APL->{alt_ins};
    $bld = $APL->{alt_bld};
    $xfile = $APL->{alt_xfile};

    xchdir($src);
    ###sysrmdir($bld);
    ###xmkdir($bld);
    ###xchdir($bld);

    # make depend fails [due to bug] without some symlinks
    ###push(@lnklist,qw(makedepend.SH Makefile.SH perl_exp.SH config_h.SH));
    foreach $tail (@lnklist) {
        $lnkto = "$src/$tail";
        symlink($lnkto,$tail) ||
            sysfault("qprlmkc: unable to symlink to '%s' -- $!\n",$lnkto);
    }

    # save us some complaints
    if ($keygo) {
        xmkdir($ins);
        xmkdir("$ins/bin");
    }

    push(@opts,"-Dprefix=$ins");
    push(@opts,"-Dstartperl=$xfile");

    push(@opts,"-Dusethreads=y");
    ###push(@opts,"-Duseithreads=y");
    ###push(@opts,"-Duselargefiles");
    ###push(@opts,"-Duse64bitall=y");

    ###push(@opts,"-Dusedevel");
    push(@opts,"-DEBUGGING=both");
    push(@opts,"-Doptimize=-gdwarf-2");

    ###push(@keyD,"DEBUG_LEAKING_SCALARS");

    foreach $opt (@keyD) {
        push(@opts,"-A","ccflags=-D$opt");
    }

    # hard to breakpoint on dynamically loaded stuff
    if (1) {
        push(@sext,"threads");
        push(@sext,"threads/shared");
    }

    push(@opts,"-Dman1dir=none");
    $env = gtxconfig("user");
    $email = $env->{email};
    $email = "anybody\@gmail.com"
        if ($keypublish);
    push(@opts,"-Dcf_email=" . $email);

    if (0) {
        push(@opts,"-Dnetdb_host_type=const void *");
        push(@opts,"-Dnetdb_hlen_type=socklen_t");
    }

    push(@opts,"-Dpager=/usr/bin/less");

    if (@sext > 0) {
        $opt = join(" ",@sext);
        push(@opts,"-Dstatic_ext=$opt");
    }

    # NOTE: to use threads, one must also use perlio :-(
    ###push(@opts,"-Duseperlio=n");

    ###push(@opts,$APL->{alt_src});

    # whip through defaults
    push(@opts,"-d","-e","-s")
        unless ($keyask);

    msgv("$pgmtail: OPTS",@opts);

    if ($keypublish) {
        foreach $opt (@opts) {
            $opt = $quo_1 . $opt . $quo_1
                 if ($opt =~ /\s/);
            printf("%s\n",$opt);
        }
    }

    unless ($keygo) {
        sysfault("$pgmtail: rerun with -go to actually do it\n");
    }

    sleep(5)
        if (sysisatty(1));

    push(@shopts,"-x")
        if ($keysh);

    {

        last unless ($keygo);

        vxsystem("sh",@shopts,"$APL->{alt_src}/Configure",@opts);
    }

    # complains on the second round
    {
        last unless ($keygo);

        last if (-e "$src/MANIFEST_NOT");

        msg("$pgmtail: renaming manifest ...\n");
        rename("$src/MANIFEST","$src/MANIFEST_NOT");

        $xfdst = xfopen(">$src/MANIFEST","qprlmkc");
        $xfdst = xfclose($xfdst,"qprlmkc");
    }
}

# cmd_qprlmkx -- make perl executable
sub cmd_qprlmkx
{
    my(@opts);

    xchdir($APL->{alt_bld});

    vxsystem("-x","make");
}

# cmd_xperl -- invoke alternate perl
sub cmd_xperl
{
    my(@argv) = @_;
    my(@opts);

    unshift(@argv,"-V")
        if ($keyQ);

    @opts = altperl(@argv);

    enveval("ALTPERL",$ALTPERL);

    {
        last if (defined($keyddd));
        xperlenv();
        exec($ALTPERL,@opts);
        sysfault("$pgmtail: exec of '%s' failed -- $!\n",$ALTPERL);
    }

    pjxgdbinit("-alien=$APL->{alt_src}",@opts);
    pjxdddloc();

    xperlenv();
    vxsystem("-x",@ddd,$ALTPERL);
}

# xperlenv -- set up environment
sub xperlenv
{
    my($opt);

    foreach $opt (@keyE) {
        if ($opt =~ /$keyval_rgx/o) {
            enveval($1,$2);
        }
    }
}

# altperl -- get alternate perl
sub altperl
{
    my(@argv) = @_;
    my(@keyD);
    local(@opts);
    my($tail,$file);
    my($logf);

    zprt(ZPXHOWEXEC,"altperl: ENTER\n");

    zprtlist(ZPXHOWEXEC,"altperl/ARGV",\@argv);

    envchk(qw(XLBIN));

    # turn on perl's internal tracing
    # NOTE: perl must be compiled with -DEBUGGING for this to work
    foreach $opt (@keyD) {
        push(@opts,"-D$opt");
        $keyLe = 1;
    }

    # run the script debugger
    push(@opts,"-dt")
        if ($keydb);

    while (1) {
        vbqdash(\@argv);
        push(@opts,$_);
        zprt(ZPXHOWEXEC,"altperl: PUSHOPT '%s'\n",$_);
    }

    # locate the script
    {
        $tail = shift(@argv);

        $file = tstloc($tail);
        last if (defined($file));

        if ($tail =~ m,^[./],) {
            $file = $tail;
            last;
        }

        # skip the XBIN entries and go direct to the final script
        if ($keyb) {
            $file = basescan($tail);
            last;
        }

        $file = "$XLBIN/$tail";
    }
    push(@opts,$file);

    # tell tskdirbug to _not_ fork/exec
    {
        last unless ($keyddd || $keydb);
        last unless (defined($tst_xfile));
        push(@opts,"-d");
    }

    enveval("LIBC_FATAL_STDERR_",1)
        if ($keyLe);

    $keyLd = 1
        if (zprtok(ZPXHOWGDB));

    if ($keyLd) {
        $logf = logfile("qprldbg");
        msg("altperl: PERLIO_DEBUG %s ...\n",$logf);
        unlink($logf);
        enveval("PERLIO_DEBUG",$logf);
    }

    # FIXME/CAE -- this needs work
    ###$glibc_ins = "/home/libc";
    ###$dir = "$glibc_ins/lib";
    ###enveval("LD_LIBRARY_PATH",$dir)
        ###if ($keyLc);

    push(@opts,@argv);
    msgv("altperl: OPTS",@opts,"...");

    zprt(ZPXHOWEXEC,"altperl: EXIT\n");

    @opts;
}

# basescan -- run perl debugger on base script
sub basescan
{
    my($basetail) = @_;
    my($topdir);
    my($basefile);
    my($bindir,@binpath);
    my($lnkfile);

    $topdir = syshome("altperl");
    sysrmdir($topdir);
    xmkdir($topdir);

    @binpath = qpbinpath();
    foreach $bindir (@binpath) {
        push(@opts,"-I$bindir");
    }

    $basefile = qplocate($basetail);
    sysfault("basescan: unable to locate '%s'\n",$basetail)
        unless (-e $basefile);
    msg("basescan: %s --> %s ...\n",$basetail,$basefile);

    # we have to create a link with the correct command name in it
    $lnkfile = "$topdir/$basetail";
    symlink($basefile,$lnkfile) ||
        sysfault("basescan: unable to symlink '%s' to '%s' -- $!\n",
            $lnkfile,$basefile);

    $lnkfile;
}

# cmd_pathx -- show path
sub cmd_pathx
{
    my(@argv) = @_;

    # execute ourself with the alternate interpreter -- we will _not_
    # recurse further because we're leaving off the -P
    {
        last if ($keyV eq "");
        exec($ALTPERL,$0);
        sysfault("$pgmtail: exec failure -- $!\n");
    }

    showpath("INC",\@INC);
    showpath("PATH");
    showpath("LD_LIBRARY_PATH");
}

# showpath -- show a path
sub showpath
{
    my($sym,$path) = @_;
    my(@path);

    printf("%s:\n",$sym);

    {
        if (ref($path)) {
            @path = @$path;
            last;
        }

        $path = $ENV{$sym};
        @path = syspathsplit($path);
    }

    foreach $path (@path) {
        printf("  %s\n",$path);
    }
}

# cmd_tskdirbug -- wrapper for tskdirbug
sub cmd_tskdirbug
{
    my($xfile);

    $xfile = tstloc();

    if ($keyhelp) {
        sysusage_less(pgmbase(),$xfile);
    }
}

# tstloc -- locate script
sub tstloc
{
    my($tail) = @_;
    my($code);
    my($xfile);

    $tail //= "tskdirbug";

    $tst_top = cdxgo("cdt");

    {
        if ($tail =~ /^tskdir/) {
            $tst_dir = "$tst_top/tskdirbug";
            last;
        }

        $tst_dir = "$tst_top/$tail";
    }

    $xfile = "$tst_dir/$tail";
    undef($xfile)
        unless (-e $xfile);

    $tst_xfile = $xfile;

    {
        last if ($keyhelp);

        last unless (defined($xfile));

        $code = qpchkgo($xfile);
        exit(1) if ($code);
    }

    $xfile;
}

Вот его основная библиотека [которая является основой для создания других вещей, таких как glibc, gcc и т. Д.]:

# altbld/altlib.pm -- common alternate make control
#
#@+
#   "-a" -- push all versions
#   "-go" -- actually do it (install)
#   "-j" -- suppress parallel build
#   "-url" -- output top url
#   "-V" -- target version to build (DEFAULT: highest)
#   "-x" -- extractable versions
#@-

_altsetup();

# _altsetup -- passive setup
sub _altsetup
{

    $altsuf{".tar.gz"} = "z";
    $altsuf{".tgz"} = "z";

    $altsuf{".tar.bz"} = "j";
    $altsuf{".tbz"} = "j";

    @altsuf = reverse(sort(keys(%altsuf)));
}

# altoptdcd -- decode options
sub altoptdcd
{
    my($arg) = @_;

    vbqnumdcd($arg,"-a",1,\$keya);
    vbqnumdcd($arg,"-go",1,\$keygo);
    vbqstrdcd($arg,"-install","",\$keyinstall);
    vbqnumdcd($arg,"-j",1,\$keyj);
    vbqstrdcd($arg,"-V","",\$keyV);
    vbqnumdcd($arg,"-x",1,\$keyx);
    vbqnumdcd($arg,"-url",1,\$keyurl);
}

# altwget -- get versions
sub altwget
{
    local($alt) = @_;
    local($remtop);
    local($foundcnt);
    my($rev,@revlist);

    sysfault("!altwget: bad pointer\n")
        unless (ref($alt));

    # most sites allow ftp with some exceptions (e.g. python.org)
    $remtop = $alt->{alt_remproto};
    $remtop //= "ftp";

    $remtop .= "://" . $alt->{alt_remhost} . "/" . $alt->{alt_remtop};

    {
        if ($keyurl) {
            printf("%s\n",$remtop);
            last;
        }

        if ($keya) {
            @revlist = @{$alt->{alt_revlist}};
            last;
        }

        push(@revlist,$alt->{alt_revuse});
    }

    foreach $rev (@revlist) {
        _altwget($rev);
    }
}

# _altwget -- pull version from website
sub _altwget
{
    my($rev) = @_;
    my($remurl,$remtail);
    my($tgzfile);
    my($dir,@dirs);
    my($subdir);
    my($cmd);

    $remurl .= $remtop;
    $remurl .= $alt->{alt_remdir};
    $remtail = $alt->{alt_name} . "-$rev" . $alt->{alt_remsuf};
    $remurl .= "/$remtail";

    xchdir($alt->{alt_netsave});
    $tgzfile = $alt->{alt_netsave} . "/$remtail";

    {
        $cmd = $altsuf{$alt->{alt_remsuf}};

        if (defined($cmd)) {
            $cmd .= "xf";
            last;
        }

        sysfault("_altwget: unknown suffix -- %s\n",$remurl);
    }

    {
        # pull the file
        unless (-e $tgzfile) {
            msgv("altwget:",NOGO("pulling"),$remurl,"...");
            if ($keygo) {
                $code = vxsystem("wget",$remurl);
                last if ($code);
            }
        }

        {
            ($dir) = homesrc("-d",$alt->{alt_name});

            unless (defined($dir)) {
                msgv("altwget: no directory found --",@dirs);
                last;
            }

            zprtx("\n")
                if ($keya);

            $subdir = "$dir/" . $alt->{alt_name} . "-$rev";
            if (-d $subdir) {
                msgv("altwget:",NOGO("removing"),$subdir);
                sysrmdir($subdir)
                    if ($keygo);
            }

            msgv("altwget:",NOGO("extracting"),$rev,"in",$dir,"...");
            $code = vxsystem("-C$dir","tar",$cmd,$tgzfile)
                if ($keygo);

            $foundcnt++;
        }

        unless ($keygo) {
            msg("altwget: rerun with -go to actually do it\n");
            last;
        }
    }

    msg("altwget: %s\n",$code ? "errors" : "complete");
}

# altverget -- get version
sub altverget
# "-ins" -- scan install directories
# "-q" -- quiet mode
{
    my(@argv) = @_;
    my($keyins,$keyq) = (0,0);
    my($keyV);
    my($svmsg);
    my($pjname);
    my($tail,@tails);
    my($dir,@dirs);
    my(@revlist);
    my($revfound);
    my($revuse);
    my($sym,$val);
    my($suf);
    my($alt);

    while (1) {
        vbqdash(\@argv);
        vbqnumdcd($_,"-ins",1,\$keyins);
        vbqstrdcd($_,"-V","",\$keyV);
        vbqnumdcd($_,"-q",1,\$keyq);
        vbqusage($_,"altverget");
    }

    $svmsg = msgqtpush($keyq);

    $pjname = shift(@argv);
    msg("altverget: project %s ...\n",$pjname);
    $alt = {};
    $alt->{alt_name} = $pjname;

    envchk(qw(NETSAVE));
    $alt->{alt_netsave} = filejoin($NETSAVE,$pjname);
    msg("altverget: netsave %s ...\n",$alt->{alt_netsave});

    $alt->{alt_ins} = "/home/alt/$pjname";

    $revlist = [];
    $alt->{alt_revlist} = $revlist;

    {
        if ($keyins) {
            @dirs = ($alt->{alt_ins});
            msg("altverget: from install ...\n");
            last;
        }

        if ($keya) {
            $keyx = 1;
        }
        else {
            last if ($pgmtail =~ /wget/);
        }

        if ($keyx) {
            msg("altverget: from netsave ...\n");
            @dirs = ($alt->{alt_netsave});
            last;
        }

        msg("altverget: from src ...\n");
        @dirs = homesrc($pjname);
    }

    foreach $dir (@dirs) {
        $alt->{alt_top} = $dir;
        $alt->{alt_src} = $dir;

        # get known versions
        if (-e $alt->{alt_src}) {
            @tails = xfdirload($alt->{alt_src},"altverget");

            foreach $tail (@tails) {
                next unless ($tail =~ s/^$pjname-//);
                foreach $suf (@altsuf) {
                    last if ($tail =~ s,$suf$,,);
                }
                push(@$revlist,$tail);
            }

            @$revlist = revsort(@$revlist);
            msgv("altverget: versions",@$revlist);

            $revfound = $revlist->[$#$revlist];

            last;
        }
    }

    # do final selection on revision
    {
        {
            # explicit command line override
            if ($keyV ne "") {
                $revuse = $keyV;
                last;
            }

            # grab an override from the environment
            $sym = "ALTREV_" . $pjname;
            $val = $ENV{$sym};
            if ($val ne "") {
                $revuse = $val;
                last;
            }

            $sym = "PJNAME";
            $val = $ENV{$sym};
            if ($val =~ s/^$pjname-//) {
                $revuse = $val;
                last;
            }

            # use searched for value
            $revuse = $revfound;
        }

        if ($revuse eq "") {
            $revuse = "unknown";
            $alt->{alt_revuse} = $revuse;
            last if ($keyins);
            last if ($keyurl);
            sysfault("altverget: no version specified\n");
        }

        msg("altverget: VERSION %s ...\n",$revuse);
        $alt->{alt_revuse} = $revuse;
    }

    $alt->{alt_src} .= "/$pjname-$revuse";
    msg("altverget: source %s ...\n",$alt->{alt_src});

    $alt->{alt_bld} = syshome("-xt","alt/build/$pjname/$pjname-$revuse");
    msg("altverget: build %s ...\n",$alt->{alt_bld});

    $alt->{alt_ins} .= "/$pjname-$revuse";
    ###$alt->{alt_ins} .= "/$pjname";
    msg("altverget: install %s ...\n",$alt->{alt_ins});

    {
        if ($revuse eq "std") {
            $alt->{alt_xfile} = "/usr/bin/$pjname";
            $alt->{alt_std} = 1;
            last;
        }

        $pjname =~ s/-.+$//;
        $alt->{alt_xfile} = $alt->{alt_ins} . "/bin/$pjname";
    }
    msg("altverget: xfile %s ...\n",$alt->{alt_xfile});

    msgqtpop($svmsg);

    $alt;
}

1;