update-alternatives.pl 23 KB

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