update-alternatives.pl 21 KB

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