home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Exec 2 / CD_Magazyn_EXEC_nr_2.iso / Linux / Archiwa / dpkg.tar.gz / dpkg-1.6.12_powerpc.nondebbin.tar / usr / sbin / update-alternatives < prev    next >
Text File  |  2000-04-07  |  20KB  |  534 lines

  1. #! /usr/bin/perl --
  2.  
  3. #use POSIX; &ENOENT;
  4. sub ENOENT { 2; }
  5. # Sorry about this, but the errno-part of POSIX.pm isn't in perl-*-base
  6.  
  7. # Global variables:
  8. #  $alink            Alternative we are managing (ie the symlink we're making/removing) (install only)
  9. #  $name             Name of the alternative (the symlink) we are processing
  10. #  $apath            Path of alternative we are offering            
  11. #  $apriority        Priority of link (only when we are installing an alternative)
  12. #  $mode             action to perform (display / install / remove / display / auto / config)
  13. #  $manual           update-mode for alternative (manual / auto)
  14. #  $state            State of alternative:
  15. #                       expected: alternative with highest priority is the active alternative
  16. #                       expected-inprogress: busy selecting alternative with highest priority
  17. #                       unexpected: alternative another alternative is active / error during readlink
  18. #                       nonexistant: alternative-symlink does not exist
  19. #  $link             Link we are working with
  20. #  @slavenames       List with names of slavelinks
  21. #  %slavenum         Map from name of slavelink to slave-index (into @slavelinks)
  22. #  @slavelinks       List of slavelinks (indexed by slave-index)
  23. #  %versionnum       Map from currently available versions into @versions and @priorities
  24. #  @versions         List of available versions for alternative
  25. #  %priorities       Map from @version-index to priority
  26. #  %slavepath        Map from (@version-index,slavename) to slave-path
  27.  
  28. $version="1.6.12"; # This line modified by Makefile
  29. sub usageversion {
  30.     print(STDERR <<END)
  31. Debian GNU/Linux update-alternatives $version.  Copyright (C) 1995
  32. Ian Jackson.  This is free software; see the GNU General Public Licence
  33. version 2 or later for copying conditions.  There is NO warranty.
  34.  
  35. Usage: update-alternatives --install <link> <name> <path> <priority>
  36.                           [--slave <link> <name> <path>] ...
  37.        update-alternatives --remove <name> <path>
  38.        update-alternatives --auto <name>
  39.        update-alternatives --display <name>
  40.        update-alternatives --config <name>
  41. <name> is the name in /etc/alternatives.
  42. <path> is the name referred to.
  43. <link> is the link pointing to /etc/alternatives/<name>.
  44. <priority> is an integer; options with higher numbers are chosen.
  45.  
  46. Options:  --verbose|--quiet  --test  --help  --version
  47.           --altdir <directory>  --admindir <directory>
  48. END
  49.         || &quit("failed to write usage: $!");
  50. }
  51. sub quit { print STDERR "update-alternatives: @_\n"; exit(2); }
  52. sub badusage { print STDERR "update-alternatives: @_\n\n"; &usageversion; exit(2); }
  53.  
  54. $altdir= '/etc/alternatives';
  55. $admindir= '/var/lib/dpkg/alternatives';
  56. $testmode= 0;
  57. $verbosemode= 0;
  58. $mode='';
  59. $manual= 'auto';
  60. $|=1;
  61.  
  62. sub checkmanymodes {
  63.     return unless $mode;
  64.     &badusage("two modes specified: $_ and --$mode");
  65. }
  66.  
  67. while (@ARGV) {
  68.     $_= shift(@ARGV);
  69.     last if m/^--$/;
  70.     if (!m/^--/) {
  71.         &quit("unknown argument \`$_'");
  72.     } elsif (m/^--(help|version)$/) {
  73.         &usageversion; exit(0);
  74.     } elsif (m/^--test$/) {
  75.         $testmode= 1;
  76.     } elsif (m/^--verbose$/) {
  77.         $verbosemode= +1;
  78.     } elsif (m/^--quiet$/) {
  79.         $verbosemode= -1;
  80.     } elsif (m/^--install$/) {
  81.         &checkmanymodes;
  82.         @ARGV >= 4 || &badusage("--install needs <link> <name> <path> <priority>");
  83.         ($alink,$name,$apath,$apriority,@ARGV) = @ARGV;
  84.         $apriority =~ m/^[-+]?\d+/ || &badusage("priority must be an integer");
  85.         $mode= 'install';
  86.     } elsif (m/^--remove$/) {
  87.         &checkmanymodes;
  88.         @ARGV >= 2 || &badusage("--remove needs <name> <path>");
  89.         ($name,$apath,@ARGV) = @ARGV;
  90.         $mode= 'remove';
  91.     } elsif (m/^--(display|auto|config)$/) {
  92.         &checkmanymodes;
  93.         @ARGV || &badusage("--$1 needs <name>");
  94.         $mode= $1;
  95.         $name= shift(@ARGV);
  96.     } elsif (m/^--slave$/) {
  97.         @ARGV >= 3 || &badusage("--slave needs <link> <name> <path>");
  98.         ($slink,$sname,$spath,@ARGV) = @ARGV;
  99.         defined($aslavelink{$sname}) && &badusage("slave name $sname duplicated");
  100.         $aslavelinkcount{$slink}++ && &badusage("slave link $slink duplicated");
  101.         $aslavelink{$sname}= $slink;
  102.         $aslavepath{$sname}= $spath;
  103.     } elsif (m/^--altdir$/) {
  104.         @ARGV || &badusage("--altdir needs a <directory> argument");
  105.         $altdir= shift(@ARGV);
  106.     } elsif (m/^--admindir$/) {
  107.         @ARGV || &badusage("--admindir needs a <directory> argument");
  108.         $admindir= shift(@ARGV);
  109.     } else {
  110.         &badusage("unknown option \`$_'");
  111.     }
  112. }
  113.  
  114. defined($aslavelink{$name}) && &badusage("name $name is both primary and slave");
  115. $aslavelinkcount{$alink} && &badusage("link $link is both primary and slave");
  116.  
  117. $mode || &badusage("need --display, --config, --install, --remove or --auto");
  118. $mode eq 'install' || !%slavelink || &badusage("--slave only allowed with --install");
  119.  
  120. if (open(AF,"$admindir/$name")) {
  121.     $manual= &gl("manflag");
  122.     $manual eq 'auto' || $manual eq 'manual' || &badfmt("manflag");
  123.     $link= &gl("link");
  124.     while (($sname= &gl("sname")) ne '') {
  125.         push(@slavenames,$sname);
  126.         defined($slavenum{$sname}) && &badfmt("duplicate slave $tsname");
  127.         $slavenum{$sname}= $#slavenames;
  128.         $slink= &gl("slink");
  129.         $slink eq $link && &badfmt("slave link same as main link $link");
  130.         $slavelinkcount{$slink}++ && &badfmt("duplicate slave link $slink");
  131.         push(@slavelinks,$slink);
  132.     }
  133.     while (($version= &gl("version")) ne '') {
  134.         defined($versionnum{$version}) && &badfmt("duplicate path $tver");
  135.        if ( -r $version ) {
  136.            push(@versions,$version);
  137.            $versionnum{$version}= $i= $#versions;
  138.            $priority= &gl("priority");
  139.            $priority =~ m/^[-+]?\d+$/ || &badfmt("priority $version $priority");
  140.            $priorities[$i]= $priority;
  141.            for ($j=0; $j<=$#slavenames; $j++) {
  142.                $slavepath{$i,$j}= &gl("spath");
  143.            }
  144.        } else {
  145.            # File not found - remove
  146.            &pr("Alternative for $name points to $version - which wasn't found.  Removing from list of alternatives.")
  147.              if $verbosemode > 0;
  148.            &gl("priority");
  149.            for ($j=0; $j<=$#slavenames; $j++) {
  150.                &gl("spath");
  151.            }
  152.        }
  153.     }
  154.     close(AF);
  155.     $dataread=1;
  156. } elsif ($! != &ENOENT) {
  157.     &quit("failed to open $admindir/$name: $!");
  158. }
  159.  
  160. if ($mode eq 'display') {
  161.     if (!$dataread) {
  162.         &pr("No alternatives for $name.");
  163.     } else {
  164.         &pr("$name - status is $manual.");
  165.         if (defined($linkname= readlink("$altdir/$name"))) {
  166.             &pr(" link currently points to $linkname");
  167.         } elsif ($! == &ENOENT) {
  168.             &pr(" link currently absent");
  169.         } else {
  170.             &pr(" link unreadable - $!");
  171.         }
  172.         $best= '';
  173.         for ($i=0; $i<=$#versions; $i++) {
  174.             if ($best eq '' || $priorities[$i] > $bestpri) {
  175.                 $best= $versions[$i]; $bestpri= $priorities[$i];
  176.             }
  177.             &pr("$versions[$i] - priority $priorities[$i]");
  178.             for ($j=0; $j<=$#slavenames; $j++) {
  179.                 next unless length($tspath= $slavepath{$i,$j});
  180.                 &pr(" slave $slavenames[$j]: $tspath");
  181.             }
  182.         }
  183.         if ($best eq '') {
  184.             &pr("No versions available.");
  185.         } else {
  186.             &pr("Current \`best' version is $best.");
  187.         }
  188.     }
  189.     exit 0;
  190. }
  191.  
  192. $best= '';
  193. for ($i=0; $i<=$#versions; $i++) {
  194.     if ($best eq '' || $priorities[$i] > $bestpri) {
  195.         $best= $versions[$i]; $bestpri= $priorities[$i];
  196.     }
  197. }
  198.  
  199. if ($mode eq 'config') {
  200.     if (!$dataread) {
  201.     &pr("No alternatives for $name.");
  202.     } else {
  203.     &config_alternatives($name);
  204.     exit 0;
  205.     }
  206. }
  207.  
  208. if (defined($linkname= readlink("$altdir/$name"))) {
  209.     if ($linkname eq $best) {
  210.         $state= 'expected';
  211.     } elsif (defined($linkname2= readlink("$altdir/$name.dpkg-tmp"))) {
  212.         $state= 'expected-inprogress';
  213.     } else {
  214.         $state= 'unexpected';
  215.     }
  216. } elsif ($! == &ENOENT) {
  217.     $state= 'nonexistent';
  218. } else {
  219.     $state= 'unexpected';
  220. }
  221.  
  222. # Possible values for:
  223. #   $manual      manual, auto
  224. #   $state       expected, expected-inprogress, unexpected, nonexistent
  225. #   $mode        auto, install, remove
  226. # all independent
  227.  
  228. if ($mode eq 'auto') {
  229.     &pr("Setting up automatic selection of $name.")
  230.       if $verbosemode > 0;
  231.     unlink("$altdir/$name.dpkg-tmp") || $! == &ENOENT ||
  232.         &quit("unable to remove $altdir/$name.dpkg-tmp: $!");
  233.     unlink("$altdir/$name") || $! == &ENOENT ||
  234.         &quit("unable to remove $altdir/$name.dpkg-tmp: $!");
  235.     $state= 'nonexistent';
  236.     $manual= 'auto';
  237. } elsif ($state eq 'nonexistent') {
  238.     if ($mode eq 'manual') {
  239.         &pr("$altdir/$name has been deleted, returning to automatic selection.")
  240.           if $verbosemode > 0;
  241.         $mode= 'auto';
  242.     }
  243. }
  244.  
  245. #   $manual      manual, auto
  246. #   $state       expected, expected-inprogress, unexpected, nonexistent
  247. #   $mode        auto, install, remove
  248. # mode=auto <=> state=nonexistent
  249.  
  250. if ($state eq 'unexpected' && $manual eq 'auto') {
  251.     &pr("$altdir/$name has been changed (manually or by a script).\n".
  252.         "Switching to manual updates only.")
  253.       if $verbosemode > 0;
  254.     $manual= 'manual';
  255. }
  256.  
  257. #   $manual      manual, auto
  258. #   $state       expected, expected-inprogress, unexpected, nonexistent
  259. #   $mode        auto, install, remove
  260. # mode=auto <=> state=nonexistent
  261. # state=unexpected => manual=manual
  262.  
  263. &pr("Checking available versions of $name, updating links in $altdir ...\n".
  264.     "(You may modify the symlinks there yourself if desired - see \`man ln'.)")
  265.   if $verbosemode > 0;
  266.  
  267. if ($mode eq 'install') {
  268.     if ($link ne $alink && $link ne '') {
  269.         &pr("Renaming $name link from $link to $alink.")
  270.           if $verbosemode > 0;
  271.         rename_mv($link,$alink) || $! == &ENOENT ||
  272.             &quit("unable to rename $link to $alink: $!");
  273.     }
  274.     $link= $alink;
  275.     if (!defined($i= $versionnum{$apath})) {
  276.         push(@versions,$apath);
  277.         $versionnum{$apath}= $i= $#versions;
  278.     }
  279.     $priorities[$i]= $apriority;
  280.     for $sname (keys %aslavelink) {
  281.         if (!defined($j= $slavenum{$sname})) {
  282.             push(@slavenames,$sname);
  283.             $slavenum{$sname}= $j= $#slavenames;
  284.         }
  285.         $oldslavelink= $slavelinks[$j];
  286.         $newslavelink= $aslavelink{$sname};
  287.         $slavelinkcount{$oldslavelink}-- if $oldslavelink ne '';
  288.         $slavelinkcount{$newslavelink}++ &&
  289.             &quit("slave link name $newslavelink duplicated");
  290.         if ($newslavelink ne $oldslavelink && $oldslavelink ne '') {
  291.             &pr("Renaming $sname slave link from $oldslavelink to $newslavelink.")
  292.               if $verbosemode > 0;
  293.             rename_mv($oldslavelink,$newslavelink) || $! == &ENOENT ||
  294.                 &quit("unable to rename $oldslavelink to $newslavelink: $!");
  295.         }
  296.         $slavelinks[$j]= $newslavelink;
  297.     }
  298.     for ($j=0; $j<=$#slavenames; $j++) {
  299.         $slavepath{$i,$j}= $aslavepath{$slavenames[$j]};
  300.     }
  301. }
  302.  
  303. if ($mode eq 'remove') {
  304.     if ($manual eq "manual" and $state = "expected") {
  305.         &pr("Removing manually selected alternative - switching to auto mode");
  306.     $manual= "auto";
  307.     }
  308.     if (defined($i= $versionnum{$apath})) {
  309.         $k= $#versions;
  310.         $versionnum{$versions[$k]}= $i;
  311.         delete $versionnum{$versions[$i]};
  312.         $versions[$i]= $versions[$k]; $#versions--;
  313.         $priorities[$i]= $priorities[$k]; $#priorities--;
  314.         for ($j=0; $j<=$#slavenames; $j++) {
  315.             $slavepath{$i,$j}= $slavepath{$k,$j};
  316.             delete $slavepath{$k,$j};
  317.         }
  318.     } else {
  319.         &pr("Alternative $apath for $name not registered, not removing.")
  320.           if $verbosemode > 0;
  321.     }
  322. }
  323.  
  324. for ($j=0; $j<=$#slavenames; $j++) {
  325.     for ($i=0; $i<=$#versions; $i++) {
  326.         last if $slavepath{$i,$j} ne '';
  327.     }
  328.     if ($i > $#versions) {
  329.         &pr("Discarding obsolete slave link $slavenames[$j] ($slavelinks[$j]).")
  330.           if $verbosemode > 0;
  331.         unlink("$altdir/$slavenames[$j]") || $! == &ENOENT ||
  332.             &quit("unable to remove $slavenames[$j]: $!");
  333.         unlink($slavelinks[$j]) || $! == &ENOENT ||
  334.             &quit("unable to remove $slavelinks[$j]: $!");
  335.         $k= $#slavenames;
  336.         $slavenum{$slavenames[$k]}= $j;
  337.         delete $slavenum{$slavenames[$j]};
  338.         $slavelinkcount{$slavelinks[$j]}--;
  339.         $slavenames[$j]= $slavenames[$k]; $#slavenames--;
  340.         $slavelinks[$j]= $slavelinks[$k]; $#slavelinks--;
  341.         for ($i=0; $i<=$#versions; $i++) {
  342.             $slavepath{$i,$j}= $slavepath{$i,$k};
  343.             delete $slavepath{$i,$k};
  344.         }
  345.         $j--;
  346.     }
  347. }
  348.         
  349. if ($manual eq 'manual') {
  350.     &pr("Automatic updates of $altdir/$name are disabled, leaving it alone.")
  351.       if $verbosemode > 0;
  352.     &pr("To return to automatic updates use \`update-alternatives --auto $name'.")
  353.       if $verbosemode > 0;
  354. } else {
  355.     if ($state eq 'expected-inprogress') {
  356.         &pr("Recovering from previous failed update of $name ...");
  357.         rename_mv("$altdir/$name.dpkg-tmp","$altdir/$name") ||
  358.             &quit("unable to rename $altdir/$name.dpkg-tmp to $altdir/$name: $!");
  359.         $state= 'expected';
  360.     }
  361. }
  362.  
  363. #   $manual      manual, auto
  364. #   $state       expected, expected-inprogress, unexpected, nonexistent
  365. #   $mode        auto, install, remove
  366. # mode=auto <=> state=nonexistent
  367. # state=unexpected => manual=manual
  368. # manual=auto => state!=expected-inprogress && state!=unexpected
  369.  
  370. open(AF,">$admindir/$name.dpkg-new") ||
  371.     &quit("unable to open $admindir/$name.dpkg-new for write: $!");
  372. &paf($manual);
  373. &paf($link);
  374. for ($j=0; $j<=$#slavenames; $j++) {
  375.     &paf($slavenames[$j]);
  376.     &paf($slavelinks[$j]);
  377. }
  378. &paf('');
  379. $best= '';
  380. for ($i=0; $i<=$#versions; $i++) {
  381.     if ($best eq '' || $priorities[$i] > $bestpri) {
  382.         $best= $versions[$i]; $bestpri= $priorities[$i]; $bestnum= $i;
  383.     }
  384.     &paf($versions[$i]);
  385.     &paf($priorities[$i]);
  386.     for ($j=0; $j<=$#slavenames; $j++) {
  387.         &paf($slavepath{$i,$j});
  388.     }
  389. }
  390. &paf('');
  391. close(AF) || &quit("unable to close $admindir/$name.dpkg-new: $!");
  392.  
  393. if ($manual eq 'auto') {
  394.     if ($best eq '') {
  395.         &pr("Last package providing $name ($link) removed, deleting it.")
  396.           if $verbosemode > 0;
  397.         unlink("$altdir/$name") || $! == &ENOENT ||
  398.             &quit("unable to remove $altdir/$name: $!");
  399.         unlink("$link") || $! == &ENOENT ||
  400.             &quit("unable to remove $altdir/$name: $!");
  401.         unlink("$admindir/$name.dpkg-new") ||
  402.             &quit("unable to remove $admindir/$name.dpkg-new: $!");
  403.         unlink("$admindir/$name") || $! == &ENOENT ||
  404.             &quit("unable to remove $admindir/$name: $!");
  405.         exit(0);
  406.     } else {
  407.         if (!defined($linkname= readlink($link)) && $! != &ENOENT) {
  408.             &pr("warning: $link is supposed to be a symlink to $altdir/$name\n".
  409.                 " (or nonexistent); however, readlink failed: $!")
  410.               if $verbosemode > 0;
  411.         } elsif ($linkname ne "$altdir/$name") {
  412.             unlink("$link.dpkg-tmp") || $! == &ENOENT ||
  413.                 &quit("unable to ensure $link.dpkg-tmp nonexistent: $!");
  414.             symlink("$altdir/$name","$link.dpkg-tmp") ||
  415.                 &quit("unable to make $link.dpkg-tmp a symlink to $altdir/$name: $!");
  416.             rename_mv("$link.dpkg-tmp",$link) ||
  417.                 &quit("unable to install $link.dpkg-tmp as $link: $!");
  418.         }
  419.         if (defined($linkname= readlink("$altdir/$name")) && $linkname eq $best) {
  420.             &pr("Leaving $name ($link) pointing to $best.")
  421.               if $verbosemode > 0;
  422.         } else {
  423.             &pr("Updating $name ($link) to point to $best.")
  424.               if $verbosemode > 0;
  425.         }
  426.         unlink("$altdir/$name.dpkg-tmp") || $! == &ENOENT ||
  427.             &quit("unable to ensure $altdir/$name.dpkg-tmp nonexistent: $!");
  428.         symlink($best,"$altdir/$name.dpkg-tmp");
  429.     }
  430. }
  431.  
  432. rename_mv("$admindir/$name.dpkg-new","$admindir/$name") ||
  433.     &quit("unable to rename $admindir/$name.dpkg-new to $admindir/$name: $!");
  434.  
  435. if ($manual eq 'auto') {
  436.     rename_mv("$altdir/$name.dpkg-tmp","$altdir/$name") ||
  437.         &quit("unable to install $altdir/$name.dpkg-tmp as $altdir/$name");
  438.     for ($j=0; $j<=$#slavenames; $j++) {
  439.         $sname= $slavenames[$j];
  440.         $slink= $slavelinks[$j];
  441.         if (!defined($linkname= readlink($slink)) && $! != &ENOENT) {
  442.             &pr("warning: $slink is supposed to be a slave symlink to\n".
  443.                 " $altdir/$sname, or nonexistent; however, readlink failed: $!")
  444.               if $verbosemode > 0;
  445.         } elsif ($linkname ne "$altdir/$sname") {
  446.             unlink("$slink.dpkg-tmp") || $! == &ENOENT ||
  447.                 &quit("unable to ensure $slink.dpkg-tmp nonexistent: $!");
  448.             symlink("$altdir/$sname","$slink.dpkg-tmp") ||
  449.                 &quit("unable to make $slink.dpkg-tmp a symlink to $altdir/$sname: $!");
  450.             rename_mv("$slink.dpkg-tmp",$slink) ||
  451.                 &quit("unable to install $slink.dpkg-tmp as $slink: $!");
  452.         }
  453.         $spath= $slavepath{$bestnum,$j};
  454.         unlink("$altdir/$sname.dpkg-tmp") || $! == &ENOENT ||
  455.             &quit("unable to ensure $altdir/$sname.dpkg-tmp nonexistent: $!");
  456.         if ($spath eq '') {
  457.             &pr("Removing $sname ($slink), not appropriate with $best.")
  458.               if $verbosemode > 0;
  459.             unlink("$altdir/$sname") || $! == &ENOENT ||
  460.                 &quit("unable to remove $altdir/$sname: $!");
  461.         unlink("$slink") || $! == &ENOENT ||
  462.             &quit("unable to remove $slink: $!");
  463.         } else {
  464.             if (defined($linkname= readlink("$altdir/$sname")) && $linkname eq $spath) {
  465.                 &pr("Leaving $sname ($slink) pointing to $spath.")
  466.                   if $verbosemode > 0;
  467.             } else {
  468.                 &pr("Updating $sname ($slink) to point to $spath.")
  469.                   if $verbosemode > 0;
  470.             }
  471.             symlink("$spath","$altdir/$sname.dpkg-tmp") ||
  472.                 &quit("unable to make $altdir/$sname.dpkg-tmp a symlink to $spath: $!");
  473.             rename_mv("$altdir/$sname.dpkg-tmp","$altdir/$sname") ||
  474.                 &quit("unable to install $altdir/$sname.dpkg-tmp as $altdir/$sname: $!");
  475.         }
  476.     }
  477. }
  478.  
  479. sub config_message {
  480.     if ($#versions == 0) {
  481.     print "\nThere is only 1 program which provides $name\n";
  482.     print "($versions[0]). Nothing to configure.\n";
  483.     return;
  484.     }
  485.     printf(STDOUT "\nThere are %s programs which provide \`$name'.\n\n", $#versions+1);
  486.     printf(STDOUT "  Selection    Command\n");
  487.     printf(STDOUT "-----------------------------------------------\n");
  488.     for ($i=0; $i<=$#versions; $i++) {
  489.     printf(STDOUT "%s%s    %s        %s\n", 
  490.         (readlink("$altdir/$name") eq $versions[$i]) ? '*' : ' ',
  491.         ($best eq $versions[$i]) ? '+' : ' ',
  492.         $i+1, $versions[$i]);
  493.     }
  494.     printf(STDOUT "\nEnter to keep the default[*], or type selection number: ");
  495. }
  496.  
  497. sub config_alternatives {
  498.     do {
  499.     &config_message;
  500.     if ($#versions == 0) { return; }
  501.     $preferred=<STDIN>;
  502.     chop($preferred);
  503.     } until $preferred eq '' || $preferred>=1 && $preferred<=$#versions+1 &&
  504.     ($preferred =~ m/[0-9]*/);
  505.     if ($preferred ne '') {
  506.     $preferred--;
  507.     print STDOUT "Using \`$versions[$preferred]' to provide \`$name'.\n";
  508.     my $spath = $versions[$preferred];
  509.     symlink("$spath","$altdir/$name.dpkg-tmp") ||
  510.         &quit("unable to make $altdir/$name.dpkg-tmp a symlink to $spath: $!");
  511.     rename_mv("$altdir/$name.dpkg-tmp","$altdir/$name") ||
  512.         &quit("unable to install $altdir/$name.dpkg-tmp as $altdir/$name: $!");
  513.     }
  514. }
  515.  
  516. sub pr { print(STDOUT "@_\n") || &quit("error writing stdout: $!"); }
  517. sub paf {
  518.     $_[0] =~ m/\n/ && &quit("newlines prohibited in update-alternatives files ($_[0])");
  519.     print(AF "$_[0]\n") || &quit("error writing stdout: $!");
  520. }
  521. sub gl {
  522.     $!=0; $_= <AF>;
  523.     length($_) || &quit("error or eof reading $admindir/$name for $_[0] ($!)");
  524.     s/\n$// || &badfmt("missing newline after $_[0]");
  525.     $_;
  526. }
  527. sub badfmt {
  528.     &quit("internal error: $admindir/$name corrupt: $_[0]");
  529. }
  530. sub rename_mv {
  531.     return (rename($_[0], $_[1]) || (system(("mv", $_[0], $_[1])) == 0));
  532. }
  533. exit(0);
  534.