LSB 5 lsb GRAPHICAL_DESKTOP 4 WindowMaker icewm 3 Epplets WMRack blackbox enlightenment ethemes icepref wmakerconf xlockmore xfce 2 wmnet 1 lesstif-mwm xbanner GNOME 5 gnome-panel nautilus gnome-control-center metacity gnome-terminal yelp nautilus-gtkhtml 4 gnome-tiles gdm gnome-applets gnome-user-docs gtk-themes file-roller gnome-network gnome-utils xlockmore gtk-engines2 gnome-vfs-extras gconf-editor 3 gnome-pilot 2 bug-buddy KDE 5 kdebase kdebase-nsplugins 5 kde-i18n-af kde-i18n-az kde-i18n-bg kde-i18n-ca kde-i18n-cs kde-i18n-da kde-i18n-de kde-i18n-el kde-i18n-en_GB kde-i18n-eo kde-i18n-es kde-i18n-et kde-i18n-fi kde-i18n-fr kde-i18n-he kde-i18n-hu kde-i18n-is kde-i18n-it kde-i18n-ja kde-i18n-ko kde-i18n-lt kde-i18n-lv kde-i18n-nl kde-i18n-no kde-i18n-no_NY kde-i18n-pl kde-i18n-pt kde-i18n-pt_BR kde-i18n-ro kde-i18n-ru kde-i18n-sk kde-i18n-sl kde-i18n-sr kde-i18n-sv kde-i18n-ta kde-i18n-th kde-i18n-tr kde-i18n-uk kde-i18n-zh_CN.GB2312 kde-i18n-zh_TW.Big5 4 kdeaddutils kdeadmin kdegraphics kdemultimedia kdenetwork krozat kdepim kdetoys kdeutils quanta 2 kdesdk kdoc VIDEO 4 xine-ui xine-oss xine-xv powerdvd RealPlayer 3 nist xanim xmms-smpeg xmovie 2 mtv mtv-fullscreen-extension 1 bcast mpeg2_movie TV 4 zapping xawtv gatos 4 KDE kwintv OFFICE 4 staroffice-de staroffice-en staroffice-es staroffice-fr staroffice-it acroread acroread-nppdf OpenOffice.org OpenOffice.org-l10n-ca OpenOffice.org-l10n-cs OpenOffice.org-l10n-da OpenOffice.org-l10n-de OpenOffice.org-l10n-el OpenOffice.org-l10n-en OpenOffice.org-l10n-es OpenOffice.org-l10n-fr OpenOffice.org-l10n-it OpenOffice.org-l10n-ja OpenOffice.org-l10n-ko OpenOffice.org-l10n-nl OpenOffice.org-l10n-pl OpenOffice.org-l10n-pt OpenOffice.org-l10n-ru OpenOffice.org-l10n-sv OpenOffice.org-l10n-tr 4 cbb gaddr xpdf moneydance 3 wv ical pyDict 2 units lyx GNOME 4 gnome-pim gnome-pim-conduits gnumeric mrproject 3 dia gnome-pilot-conduits Guppi 2 ggv gnucash KDE 3 koffice 3 koffice-i18n-az koffice-i18n-bg koffice-i18n-cs koffice-i18n-da koffice-i18n-de koffice-i18n-en_GB koffice-i18n-eo koffice-i18n-es koffice-i18n-et koffice-i18n-fr koffice-i18n-hu koffice-i18n-it koffice-i18n-ja koffice-i18n-lt koffice-i18n-mt koffice-i18n-nl koffice-i18n-no koffice-i18n-no_NY koffice-i18n-pl koffice-i18n-pt koffice-i18n-pt_BR koffice-i18n-ro koffice-i18n-ru koffice-i18n-sk koffice-i18n-sl koffice-i18n-sv koffice-i18n-ta koffice-i18n-tr koffice-i18n-uk 2 klyx SOUND 5 sox 4 aumix 4 KDE xmms-arts AUDIO 4 grip xmms xmms-skins 4 GNOME gnome-audio gnome-media 4 KDE kdelibs-sound 4 3D xmms-mesa 3 cdp cdparanoia cdrecord-cdda2wav space_sounds timidity-instruments xmms-esd xmms-kjofol-skins xmms-more-vis-plugins 3 GNOME gnome-audio-extra 2 mokmod mp3info mpg123 playmidi playmidi-X11 xmms-mikmod 4 HW"Rio 500" rio500 grio500 ACCESSIBILITY 2 gtkeyboard PUBLISHING 5 enscript ghostscript-module-X 4 ghostscript-utils gv psutils texinfo nlpr 2 latex2html jadetex tetex-afm tetex-dvips tetex-latex tetex-xdvi tetex-latex-arab tetex-latex-heb docbook-dtd31-sgml 2 BOOKS tetex-doc 1 docbook-style-dsssl openjade sgml-tools ghostscript-module-SVGALIB cttex 1 BOOKS docbook-style-dsssl-doc 5 CUPS cups-drivers xpp 5 CUPS || LPR foomatic 1 CUPS hpoj SHELLS 3 zsh 3 BOOKS bash-doc zsh-doc 2 eshell pdksh tcsh 1 bash1 SCIENCES 5 3D openuniverse 4 gnuplot gtkgraphh 3 xlispstat HDF 2 mathplot octave 1 xoscope EDITORS 4 emacs-X11 3 GXedit vim-X11 yudit 2 nedit cooledit emacs-tramp joe emacs-leim jed-xjed xemacs xemacs-extras xemacs-info 1 auctex emacs-el jed xemacs-el emacs-nox xwpe xwpe-X11 GNOME 4 gedit TEXT_TOOLS 5 words 4 groff patch recode rgrep 4 ispell-af ispell-br ispell-ca ispell-cs ispell-da ispell-de ispell-el ispell-en ispell-eo ispell-es ispell-fi ispell-fr ispell-ga ispell-gd ispell-gv ispell-id ispell-it ispell-nl ispell-no ispell-pl ispell-pt ispell-pt_BR ispell-ro ispell-ru ispell-sk ispell-sl ispell-sv 3 ed 2 groff-gxditview lout BOOKS 3 gawk-doc 1 lout-doc COMMUNICATIONS 4 efax 3 jpilot pilot-link 2 hylafax-server hylafax-client dip 2 lrzsz mgetty mgetty-contrib mgetty-sendfax mgetty-viewfax mgetty-voice minicom 1 jpilot-Mail jpilot-syncmal statserial tkbabel TERMINALS 5 open xterm 4 screen kon2 3 Eterm vlock 1 aterm x3270 4 KDE ktelnet 4 GNOME gnome-telnet 4 LOCALES"ja" kterm NETWORKING_CHAT 3 talk ytalk NETWORKING_CHAT_SERVER 4 jabber 3 talk-server NETWORKING_FILE_TRANSFER 5 lftp mirrordir rsync 4 gftp rdist 3 fmirror ncftp tftp 3 GNOME dpsftp 2 uucp NETWORKING_FILE_TRANSFER_SERVER 4 proftpd bwbserver_linux 2 wu-ftpd anonftp NETWORKING_LDAP_SERVER 4 openldap directory_administrator NETWORKING_INSTANT_MESSAGING 4 licq 3 everybuddy licq-console licq-rms GNOME 5 aspell-br aspell-ca aspell-cs aspell-da aspell-de aspell-de_CH aspell-en aspell-en_CA aspell-en_GB aspell-eo aspell-es aspell-fr aspell-it aspell-nl aspell-no aspell-pl aspell-sv 4 gnomeicu gabber gaim 3 gtk+licq NETWORKING_IRC 3 BitchX mozilla-irc 3 GNOME xchat 2 irssi 1 eggdrop NETWORKING_FIREWALLING_SERVER 5 iproute2 routed iptables 3 prelude 1 portsentry NETWORKING_GROUPWARE_SERVER 4 phpgroupware bwbserver_linux NETWORKING_MAIL 5 mailx metamail 4 faces mozilla-mail evolution 3 fetchmail urlview mutt 3 !GNOME !KDE xmailbox 2 FaxMail comsat elm faces-xface 1 exmh sylpheed fetchmail-daemon fetchmailconf NETWORKING_MAIL_SERVER 5 postfix 4 mailman NETWORKING_NEWS 5 GNOME pan 2 slrn tin trn 1 slrn-pull xrn NETWORKING_NEWS_SERVER 4 inn 3 inews NETWORKING_OTHER 2 finger fwhois ucd-snmp-utils htdig macutils NETWORKING_OTHER_SERVER 3 dhcp-server gated timed ntp 3 intimed mcserv nscd imap pidentd rdate bootparamd cleanfeed ucd-snmp leafnode cvsweb nut-server XFree86-Xvfb XFree86-Xnest 2 heartbeat diald finger-server mars-nwe NIS 5 ypbind NIS_SERVER 5 ypserv NETWORKING_REMOTE_ACCESS 5 openssh-clients telnet telnet-client-krb5 KDE lisa 4 traceroute rfbdrake 3 vnc 2 rsh 2 BOOKS vnc-doc NETWORKING_REMOTE_ACCESS_SERVER 5 openssh-server 4 rfbdrake 2 vnc-server 1 telnet-server-krb5 rsh-server NETWORKING_DNS 4 bind-utils NETWORKING_DNS_SERVER 5 bind 4 caching-nameserver 1 nslint NETWORKING_FILE 4 samba-client nfs-utils-clients 2 arkeia-gui arkeia-client arkeia-arkc 2 GNOME gnomba gtm 2 autofs 1 am-utils NETWORKING_FILE_SERVER 5 nfs-utils 4 samba-server bwbserver_linux 3 BOOKS samba-doc 2 arkeia-server samba-winbind 3 squid squidGuard NETWORKING_WWW 3 lynx 4 !LOCALES"eu" netscape-communicator netscape-plugins 4 wget links mozilla Flashplayer crossover-plugin-demo j2re 4 GNOME screem !LOCALES"eu" galeon 3 plugger opera bluefish NETWORKING_WWW_SERVER 5 apache apache-mod_perl mod_ssl mod_php 4 apache-suexec bwbserver_linux 4 BOOKS apache-manual 3 php-dba_gdbm_db2 php-gd php-imap php-ldap php-manual php-mysql php-oracle php-pgsql php-readline php mod_sxnet auth_ldap HTML-Embperl 2 ApacheJServ 1 Zope Zope-core Zope-pcgi Zope-zserver GRAPHICS 4 ImageMagick giftrans gimp gphoto gphoto2 qiv ac3d 3 gimp-data-extras gqview sketch xwpick xli 2 gif2png gimp-perl xpcd xfig xpcd-gimp gd-utils cameleo 1 libgr-progs libungif-progs qcad transfig xpaint xmorph 1 3D Mesa-demos GNOME 4 gnome-iconedit 3 ee ARCHIVING 5 dump ncompress sharutils unzip 4 gtkzip zip 3 unarj unstuff mt-st 2 taper 1 lha GNOME 4 gnozip 3 gtktalog BURNER 5 mkisofs cdrecord 4 GNOME gnome-toaster gcombust 4 X xcdroast 2 X eroaster DEVELOPMENT 3 cdrecord-devel SCANNER 5 sane-frontends 4 gimp 4 xsane PHOTO 4 gphoto gphoto2 3 gnomemeeting openmcu DATABASES 5 postgresql 3 MySQL-client MySQL-shared DATABASES_SERVER 4 postgresql-server 3 MySQL 3 postgresql-perl postgresql-python 2 postgresql-jdbc postgresql-tk postgresql-odbc postgresql-tcl postgresql-test DEVELOPMENT 4 perl-Mysql 3 postgresql-devel 1 MySQL-bench MySQL-devel GAMES 4 sin-demo 4 clanbomber freeciv lbreakout2 toppler frozen-bubble 3 shogo-demo 3 cxhextris rocksndiamonds powermanga mures methane 2 Maelstrom pingus ltris penguin-command pysol xtrojka bunnies xpilot trophy xboard xgammon xkobo xpat2 xpuzzles xsoldier xfishtank 1 7colors xrally fortune-mod nil GNOME 4 gnome-games 3 gnome-chess 2 3D gtulpas 1 gtkgo DEVELOPMENT 2 gnomes-games-devel KDE 4 kdegames DEVELOPMENT 2 kdegames-devel 3D 4 csmash armagetron !HW"Riva.*128" chromium tuxracer 3 !HW"Riva.*128" !HW"Rage X[CL]" !HW"Rage Mobility (?:P\/M|L) " !HW"3D Rage (?:LT|Pro)" bzflag DEVELOPMENT 5 autoconf automake m4 make 3 autoconf2.5 1 tmake pmake pmake-customs 3 libtool binutils ltrace gdb gcc 2 gperf cdecl cproto indent ElectricFence 1 egcs glibc-profile xxgdb 4 gcc-c++ libstdc++5-devel libstdc++-devel 2 libsigc++-examples 1 egcs-c++ 3 bison flex 2 byacc 2 doxygen C++2LaTeX 3 jikes kaffe 1 gcc-java 5 cvs rcs 2 diffstat tkcvs 3 swig 4 python veepee tkinter 3 libpython2.2-devel python-devel python-imaging pygtk-glarea pygtk pygtk-libglade rpm-python 4 perl perl-Term-Readline-Gnu perl-libnet perl-libwww-perl perl-devel 3 perl-DBI perl-Digest-MD5 perl-IO-stringy perl-PDL perl-Parse-RecDescent perl-GTK-GLArea perl-Tk perlftlib eperl perl-URI perl-DB_File perl-Data-ShowTable perl-HTML-Parser perl-HTML-SimpleParse perl-MIME-Base64 perl-MIME-tools perl-MP3-Info perl-MailTools perl-Msgcat 4 rpm-build 3 rpmlint rpm-devel 3 kernel-source 2 gcc-g77 nasm dev86 1 gcc-objc 2 teyjus gprolog ocaml umb-scheme mawk guile clisp SmallEiffel p2c ghc ghc-prof happy haskell-GTK haskell-GTK-devel hugs98 mercury swi-prolog ruby-extensions ruby-gtk ruby 4 gettext-devel BOOKS 2 pam-doc python-docs slang-doc kernel-doc nasm-doc qt2-doc ruby-doc lkmpg KDE 3 kdevelop 3 kdebase-devel kdegraphics-devel kdelibs-devel kdelibs-sound-devel kdemultimedia-devel kdenetwork-devel 1 kdesupport-devel kdeaddutils-devel koffice-devel GNOME 4 perl-GTK-Glade perl-GTK-Gnome 3 memprof glade gnome-guile pygnome libgnomeui2_0-devel gnome-guile-devel gnome-pim-devel gob 2 pygnome-applet pygnome-capplet pygnome-libglade rep-gtk-gnome libgnomemm-1.2_9-devel gnomemm-devel libgnome-pilot1-devel gnome-pilot-devel glademm 1 gnucash-devel rep-gtk-libglade DEVELOPMENT_OTHER 2 ImageMagick-devel Mesa-common-devel libXaw3d7-devel Xaw3d-devel detect-devel libgd2-devel gd-devel p2c-devel libgmp3-devel gmp-devel libguile9-devel guile-devel libgr-devel libjpeg62-devel libjpeg-devel libpng3-devel libpng-devel libtermcap2-devel libtermcap-devel libtiff3-devel libtiff-devel libungif4-devel libungif-devel libxml2-devel libxml-devel linuxconf-devel libslang1-devel slang-devel sox-devel zlib1-devel zlib-devel XFree86-devel dev86-devel libgdk-pixbuf2-devel gdk-pixbuf-devel libgimp1.2_1-devel gimp-devel libgpm1-devel gpm-devel kudzu-devel libghttp1-devel libghttp-devel libgtop2.0_0-devel libgtop-devel libmikmod2-devel libmikmod-devel librep9-devel librep-devel libunicode-devel popt-devel pwdb-devel t1lib1-devel t1lib-devel ucd-snmp-devel mpeg_lib-devel WindowMaker-devel aalib-devel libadns1-devel adns-devel alsa-lib-devel audiofile-devel libcups1-devel cups-devel e2fsprogs-devel egcs-objc-devel libg-wrap2-devel g-wrap-devel gkrellm-devel ibtk libPropList-devel licq-devel openldap-devel libparted1.6-devel parted-devel pciutils-devel pilot-link-devel svgalib-devel recode-devel libaspell10-devel aspell-devel cracklib-devel faces-devel fnlib-devel freetype-devel libgtk+mdk0.1_6-devel gtk+mdk-devel libgtkglarea5-devel gtkglarea-devel XFree86-static-libs imap-devel php-devel libpth14-devel pth-devel libsane1-devel sane-devel swig-devel xdelta-devel isapnptools-devel libpango1.0_0-devel pango-devel readline-devel MONITORING 5 procinfo psacct 5 PCMCIA apmd 4 lsof swatch tcpdump traceroute 3 iplog arpwatch lslk nmap nmap-frontend procps-X11 xcpustate xsysinfo 2 cfengine gkrellm gps rusers mon xosview 3D xtraceroute 1 logcheck bonnie GNOME 4 gnome-system-monitor FILE_TOOLS 5 file gnupg mkxauth mtools slocate 4 symlinks 3 dosfstools draksync mc tree 2 git gentoo sfm xwc FileRunner 1 xdelta WEBMIN 3 webmin WIZARDS 5 drakwizard CONFIG 4 linuxconf linuxconf-lang-cs linuxconf-lang-de linuxconf-lang-es linuxconf-lang-fi linuxconf-lang-fr linuxconf-lang-hu linuxconf-lang-it linuxconf-lang-ko linuxconf-lang-no linuxconf-lang-pt linuxconf-lang-ro linuxconf-lang-sk linuxconf-lang-sv linuxconf-lang-zh 4 X gnome-linuxconf 3 ipvsadm quota usernet nut 2 gfcc control-panel adjtimex isicom xinput timeconfig samba-swat 1 ipxutils BOOKS 3 mandrake_doc-de mandrake_doc-en mandrake_doc-es mandrake_doc-fr mandrake_doc-it mandrake_doc-ru X 5 XFree86 rxvt XFree86-75dpi-fonts urw-fonts 5 icewm-light 4 vim-enhanced 4 gurpmi rpmdrake drakconf userdrake fonts-ttf-decoratives fonts-ttf-west_european mandrake-mime menudrake mandrake_desk mdkonline drakfirsttime gtk-engines bootsplash 4 LOCALES"ja" || LOCALES"ko" || LOCALES"zh" rxvt-CJK 3 XFree86-100dpi-fonts draksync drakprofile 3 USB usbview 2 LOCALES"ja" || LOCALES"ko" || LOCALES"zh" jmcce 2 tksysv imlib-cfgeditor 1 DrakeLogo Mesa xtoolwait X11R6-contrib GNOME 3 gnorpm 5 xcin Chinput xa+cv xvnkb FreeWnn ami kinput2-wnn4 2 app-defaults-be app-defaults-cs app-defaults-ga app-defaults-ru app-defaults-th app-defaults-uk 5 CHARSET"iso-8859-13" fonts-type1-baltic LOCALES"ru" || LOCALES"uk" XFree86-cyrillic-fonts LOCALES"he" fonts-hebrew-elmar LOCALES"hy" fonts-ttf-armenian LOCALES"ja" fonts-ttf-japanese LOCALES"ko" fonts-ttf-korean LOCALES"ta" fonts-ttf-tscii fonts-bitmap-tscii LOCALES"th" fonts-ttf-thai LOCALES"zh_CN" || LOCALES"zh" fonts-ttf-gb2312 LOCALES"zh_TW" || LOCALES"zh" taipeifonts fonts-ttf-big5 DOCS 5 man info man-pages SYSTEM 5 at MAKEDEV eject ldetect devfsd locales iputils urpmi cpio msec tmpwatch 5 HIGH_SECURITY libsafe kernel-secure-2.4.19.16mdk kernel-secure 5 BIGMEM kernel-enterprise-2.4.19.16mdk kernel-enterprise 5 SMP kernel-smp-2.4.19.16mdk kernel-smp 5 PCMCIA pcmcia-cs 5 USB hotplug 5 HW"nForce.*(?:Audio|Network)" NVIDIA_nforce-2.4.19-16mdk BIGMEM NVIDIA_nforce-2.4.19-16mdk-enterprise 4 ftp-client-krb5 gpm hexedit strace sudo grub procmail gnupg 3 bc 2 sndconfig kernel-utils acpid adns audiofile freeswan awesfx fbset vlan-utils 1 fdutils genromfs mailcap pinfo BOOKS 5 man-pages-cs man-pages-da man-pages-de man-pages-es man-pages-fr man-pages-hu man-pages-id man-pages-it man-pages-ja man-pages-ko man-pages-pl man-pages-ru man-pages-zh 3 grub-doc lilo-doc howto-html-de howto-html-el howto-html-en howto-html-es howto-html-fr howto-html-hr howto-html-hu howto-html-id howto-html-it howto-html-ja howto-html-ko howto-html-nl howto-html-pl howto-html-ro howto-html-sl howto-html-sv howto-html-zh 4 NIS yp-tools 3 PCMCIA irda-utils 3 USB usbutils 4 LOCALES"ar" || LOCALES"fa" || LOCALES"he" || LOCALES"yi" acon 3 LOCALES"zh" zh-autoconvert EMULATORS 3 wine 2 BasiliskII-jit 1 BasiliskII 2 xdosemu 1 xmame xmess INSTALL NOCOPY 5 kernel-2.4.19.16mdk kernel-2.4.19.16mdk kernel kernel-smp-2.4.19.16mdk kernel-smp-2.4.19.16mdk kernel-smp kernel-enterprise-2.4.19.16mdk kernel-enterprise-2.4.19.16mdk kernel-enterprise raidtools lvm reiserfsprogs jfsprogs xfsprogs alsa alsa-utils 4 XFree86 5 pptp-adsl dhcpcd dhcpxd dhcp-client isdn4net isdn-light isdn4k-utils ibod rp-pppoe pump wireless-tools speedtouch ppp nfs-utils-clients autologin ntp cups-drivers samba ncpfs hpoj ucd-snmp libptal0 libhpojip0 libsnmp0 xojpanel libsane-hpoj0 ipchains shorewall iptables printer-utils rlpr samba-client xpp pdq printer-testpages nmap scli net-tools cups lpr foomatic gimpprint nc sndconfig ImageMagick ghostscript printer-filters mpage a2ps ppdfilt libppd1 gpr groff libgimpprint1 numlock curl sane-backends sane-frontends xsane xsane-gimp mtools mtoolsfm hotplug dev ypbind speedtouch_mgmt 4 XFree86-server XFree86-FBDev # 4 XFree86-SVGA XFree86-server XFree86-Mach64 XFree86-FBDev # XFree86-glide-module Device3Dfx Glide_V3-DRI Glide_V5 Mesa # 3 XFree86-S3 XFree86-S3V XFree86-VGA16 # 2 XFree86-8514 XFree86-AGX XFree86-I128 XFree86-Mach32 XFree86-Mach8 XFree86-Mono XFree86-P9000 XFree86-W32 # 1 XFree86-3DLabs XFree86-Sun XFree86-SunMono XFree86-Sun24 19 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
package install_steps_interactive; # $Id$
use diagnostics;
use strict;
use vars qw(@ISA $new_bootstrap);
@ISA = qw(install_steps);
#-######################################################################################
#- misc imports
#-######################################################################################
use common;
use partition_table qw(:types);
use partition_table::raw;
use install_steps;
use install_interactive;
use install_any;
use install_messages;
use detect_devices;
use run_program;
use devices;
use fsedit;
use loopback;
use mouse;
use modules;
use modules::interactive;
use lang;
use keyboard;
use any;
use fs;
use log;
#-######################################################################################
#- In/Out Steps Functions
#-######################################################################################
sub errorInStep {
my ($o, $err) = @_;
$o->ask_warn(N("Error"), [ N("An error occurred"), formatError($err) ]);
}
sub kill_action {
my ($o) = @_;
$o->kill;
}
sub charsetChanged {
my ($_o) = @_;
}
#-######################################################################################
#- Steps Functions
#-######################################################################################
#------------------------------------------------------------------------------
sub selectLanguage {
my ($o) = @_;
$o->{locale}{lang} = any::selectLanguage($o, $o->{locale}{lang}, $o->{locale}{langs} ||= {});
install_steps::selectLanguage($o);
if ($o->isa('interactive::gtk')) {
$o->ask_warn('', formatAlaTeX(
"If you see this message it is because you chose a language for
which DrakX does not include a translation yet; however the fact
that it is listed means there is some support for it anyway.
That is, once GNU/Linux will be installed, you will be able to at
least read and write in that language; and possibly more (various
fonts, spell checkers, various programs translated etc. that
varies from language to language).")) if $o->{locale}{lang} !~ /^en/ && !lang::load_mo();
} else {
#- no need to have this in po since it is never translated
$o->ask_warn('', "The characters of your language can't be displayed in console,
so the messages will be displayed in english during installation") if $ENV{LANGUAGE} eq 'C';
}
}
sub acceptLicense {
my ($o) = @_;
my $r = 'Refuse';
($::recovery ?
$o->ask_yesorno('', N("Do you want to recover your system?"), 0) :
$o->ask_from_({ title => N("License agreement"),
cancel => N("Quit"),
messages => formatAlaTeX(install_messages::main_license() . "\n\n\n" . install_messages::warning_about_patents()),
interactive_help_id => 'acceptLicense',
callbacks => { ok_disabled => sub { $r eq 'Refuse' } },
},
[ { list => [ N_("Accept"), N_("Refuse") ], val => \$r, type => 'list', format => sub { translate($_[0]) } } ]))
or do {
install_any::ejectCdrom();
$o->exit;
};
}
#------------------------------------------------------------------------------
sub selectKeyboard {
my ($o, $clicked) = @_;
my $from_usb = keyboard::from_usb();
my $l = keyboard::lang2keyboards(lang::langs($o->{locale}{langs}));
if ($::expert || $clicked || !($from_usb || @$l && $l->[0][1] >= 90) || listlength(lang::langs($o->{locale}{langs})) > 1) {
add2hash($o->{keyboard}, $from_usb);
my @best = uniq($from_usb ? $from_usb->{KEYBOARD} : (), (map { $_->[0] } @$l), 'us_intl');
my $format = sub { translate(keyboard::KEYBOARD2text($_[0])) };
my $other;
my $ext_keyboard = my $KEYBOARD = $o->{keyboard}{KEYBOARD};
$o->ask_from_(
{ title => N("Keyboard"),
messages => N("Please choose your keyboard layout."),
interactive_help_id => 'selectKeyboard',
advanced_messages => N("Here is the full list of keyboards available"),
advanced_label => N("More"),
callbacks => { changed => sub { $other = $_[0] == 1 } },
},
[ if_(@best > 1, { val => \$KEYBOARD, type => 'list', format => $format, sort => 1,
list => [ @best ] }),
{ val => \$ext_keyboard, type => 'list', format => $format,
list => [ difference2([ keyboard::KEYBOARDs() ], \@best) ], advanced => @best > 1 }
]);
$o->{keyboard}{KEYBOARD} = $other ? $ext_keyboard : $KEYBOARD;
delete $o->{keyboard}{unsafe};
}
keyboard::group_toggle_choose($o, $o->{keyboard}) or goto &selectKeyboard;
install_steps::selectKeyboard($o);
}
#------------------------------------------------------------------------------
sub selectInstallClass {
my ($o) = @_;
if (my @l = install_any::find_root_parts($o->{fstab}, $o->{prefix})) {
log::l("proposing to upgrade partitions " . join(" ", map { $_->{part}{device} } @l));
my @releases = uniq(map { $_->{release} } @l);
if (@releases != @l) {
#- same release name so adding the device to differentiate them:
$_->{release} .= " ($_->{part}{device})" foreach @l;
}
my $p;
$o->ask_from_({ title => N("Install/Upgrade"),
messages => N("Is this an install or an upgrade?"),
interactive_help_id => 'selectInstallClass',
},
[ { val => \$p,
list => [ @l, N_("Install") ],
type => 'list',
format => sub { ref($_[0]) ? N("Upgrade %s", $_[0]{release}) : translate($_[0]) }
} ]);
if (ref $p) {
my $part = $p->{part};
log::l("choosing to upgrade partition $part->{device}");
install_any::use_root_part($o->{all_hds}, $part, $o->{prefix});
foreach (grep { $_->{mntpoint} } @{$o->{fstab}}) {
my ($options, $_unknown) = fs::mount_options_unpack($_);
$options->{encrypted} or next;
$o->ask_from_({ focus_first => 1 },
[ { label => N("Encryption key for %s", $_->{mntpoint}),
hidden => 1, val => \$_->{encrypt_key} } ]);
}
$o->{isUpgrade} = 1;
}
}
}
#------------------------------------------------------------------------------
sub selectMouse {
my ($o, $force) = @_;
$force ||= $o->{mouse}{unsafe} || 1;
if ($force) {
my $prev = $o->{mouse}{type} . '|' . $o->{mouse}{name};
$o->ask_from_({ messages => N("Please choose your type of mouse."),
interactive_help_id => 'selectMouse',
},
[ { list => [ mouse::fullnames() ], separator => '|', val => \$prev, format => sub { join('|', map { translate($_) } split('\|', $_[0])) } } ]);
$o->{mouse} = mouse::fullname2mouse($prev);
}
if ($force && $o->{mouse}{type} eq 'serial') {
$o->{mouse}{device} =
$o->ask_from_listf_raw({ title => N("Mouse Port"),
messages => N("Please choose which serial port your mouse is connected to."),
interactive_help_id => 'selectSerialPort',
},
\&mouse::serial_port2text,
[ mouse::serial_ports() ]) or return &selectMouse;
}
if (arch() =~ /ppc/ && $o->{mouse}{nbuttons} == 1) {
#- set a sane default F11/F12
$o->{mouse}{button2_key} = 87;
$o->{mouse}{button3_key} = 88;
$o->ask_from('', N("Buttons emulation"),
[
{ label => N("Button 2 Emulation"), val => \$o->{mouse}{button2_key}, list => [ mouse::ppc_one_button_keys() ], format => \&mouse::ppc_one_button_key2text },
{ label => N("Button 3 Emulation"), val => \$o->{mouse}{button3_key}, list => [ mouse::ppc_one_button_keys() ], format => \&mouse::ppc_one_button_key2text },
]) or return;
}
if ($o->{mouse}{device} eq "usbmouse") {
modules::interactive::load_category($o, 'bus/usb', 1, 1);
eval {
devices::make("usbmouse");
modules::load(qw(hid mousedev usbmouse));
};
}
$o->SUPER::selectMouse;
1;
}
#------------------------------------------------------------------------------
sub setupSCSI {
my ($o) = @_;
if (!$::noauto && arch() =~ /i.86/) {
if ($o->{pcmcia} ||= !$::testing && c::pcmcia_probe()) {
my $w = $o->wait_message(N("PCMCIA"), N("Configuring PCMCIA cards..."));
my $results = modules::configure_pcmcia($o->{pcmcia});
$w = undef;
$results and $o->ask_warn('', $results);
}
}
{
my $_w = $o->wait_message(N("IDE"), N("Configuring IDE"));
modules::load(modules::category2modules('disk/cdrom'));
}
modules::interactive::load_category($o, 'bus/firewire', 1);
my $have_non_scsi = detect_devices::hds(); #- at_least_one scsi device if we have no disks
modules::interactive::load_category($o, 'disk/scsi|hardware_raid|firewire', 1, !$have_non_scsi);
modules::interactive::load_category($o, 'disk/scsi|hardware_raid|firewire') if !detect_devices::hds(); #- we really want a disk!
install_interactive::tellAboutProprietaryModules($o);
install_any::getHds($o, $o);
}
sub ask_mntpoint_s { #- }{}
my ($o, $fstab) = @_;
my @fstab = grep { isTrueFS($_) } @$fstab;
@fstab = grep { isSwap($_) } @$fstab if @fstab == 0;
@fstab = @$fstab if @fstab == 0;
die \N("No partition available") if @fstab == 0;
{
my $_w = $o->wait_message('', N("Scanning partitions to find mount points"));
install_any::suggest_mount_points($fstab, $o->{prefix}, 'uniq');
log::l("default mntpoint $_->{mntpoint} $_->{device}") foreach @fstab;
}
if (@fstab == 1) {
$fstab[0]{mntpoint} = '/';
} else {
$o->ask_from_({ messages => N("Choose the mount points"),
interactive_help_id => 'ask_mntpoint_s',
},
[ map { { label => partition_table::description($_),
val => \$_->{mntpoint},
not_edit => 0,
list => [ '', fsedit::suggestions_mntpoint(fsedit::empty_all_hds()) ] }
} grep { !$_->{real_mntpoint} || common::usingRamdisk() } @fstab ]) or return;
}
$o->SUPER::ask_mntpoint_s($fstab);
}
#------------------------------------------------------------------------------
sub doPartitionDisks {
my ($o) = @_;
if (arch() =~ /ppc/ && detect_devices::get_mac_generation() =~ /NewWorld/) { #- need to make bootstrap part if NewWorld machine - thx Pixel ;^)
if (defined $partition_table::mac::bootstrap_part) {
#- don't do anything if we've got the bootstrap setup
#- otherwise, go ahead and create one somewhere in the drive free space
} else {
undef = $partition_table::mac::freepart; #- please "perl -w"
my $freepart = $partition_table::mac::freepart;
if ($freepart && $freepart->{size} >= 1) {
log::l("creating bootstrap partition on drive /dev/$freepart->{hd}{device}, block $freepart->{start}");
$partition_table::mac::bootstrap_part = $freepart->{part};
log::l("bootstrap now at $partition_table::mac::bootstrap_part");
fsedit::add($freepart->{hd}, { start => $freepart->{start}, size => 1 << 11, type => 0x401, mntpoint => '' }, $o->{all_hds}, { force => 1, primaryOrExtended => 'Primary' });
$new_bootstrap = 1;
} else {
$o->ask_warn('', N("No free space for 1MB bootstrap! Install will continue, but to boot your system, you'll need to create the bootstrap partition in DiskDrake"));
}
}
}
if (!$o->{isUpgrade}) {
install_interactive::partitionWizard($o);
}
}
#------------------------------------------------------------------------------
sub rebootNeeded {
my ($o) = @_;
$o->ask_warn('', N("You need to reboot for the partition table modifications to take place"));
install_steps::rebootNeeded($o);
}
#------------------------------------------------------------------------------
sub choosePartitionsToFormat {
my ($o, $fstab) = @_;
$o->SUPER::choosePartitionsToFormat($fstab);
my @l = grep { !$_->{isMounted} && $_->{mntpoint} &&
(!isSwap($_) || $::expert) &&
(!isFat_or_NTFS($_) || $_->{notFormatted} || $::expert) &&
(!isOtherAvailableFS($_) || $::expert || $_->{toFormat})
} @$fstab;
$_->{toFormat} = 1 foreach grep { isSwap($_) && !$::expert } @$fstab;
return if @l == 0 || !$::expert && every { $_->{toFormat} } @l;
#- keep it temporary until the guy has accepted
$_->{toFormatTmp} = $_->{toFormat} || $_->{toFormatUnsure} foreach @l;
$o->ask_from_(
{ messages => N("Choose the partitions you want to format"),
interactive_help_id => 'formatPartitions',
advanced_messages => N("Check bad blocks?"),
},
[ map {
my $e = $_;
({
text => partition_table::description($e), type => 'bool',
val => \$e->{toFormatTmp}
}, if_(!isLoopback($_) && !isThisFs("reiserfs", $_) && !isThisFs("xfs", $_) && !isThisFs("jfs", $_), {
text => partition_table::description($e), type => 'bool', advanced => 1,
disabled => sub { !$e->{toFormatTmp} },
val => \$e->{toFormatCheck}
})) } @l ]
) or die 'already displayed';
#- ok now we can really set toFormat
foreach (@l) {
$_->{toFormat} = delete $_->{toFormatTmp};
$_->{isFormatted} = 0;
}
}
sub formatMountPartitions {
my ($o, $_fstab) = @_;
my $w;
catch_cdie {
fs::formatMount_all($o->{all_hds}{raids}, $o->{fstab}, $o->{prefix}, sub {
my ($msg) = @_;
$w ||= $o->wait_message('', $msg);
$w->set($msg);
});
} sub {
$@ =~ /fsck failed on (\S+)/ or return;
$o->ask_yesorno('', N("Failed to check filesystem %s. Do you want to repair the errors? (beware, you can lose data)", $1), 1);
};
undef $w; #- help perl (otherwise wait_message stays forever in newt)
die \N("Not enough swap space to fulfill installation, please add some") if availableMemory() < 40 * 1024;
}
#------------------------------------------------------------------------------
sub setPackages {
my ($o, $rebuild_needed) = @_;
my $w = $o->wait_message('', $rebuild_needed ? N("Looking for available packages and rebuilding rpm database...") :
N("Looking for available packages..."));
install_any::setPackages($o, $rebuild_needed);
$w->set(N("Looking at packages already installed..."));
pkgs::selectPackagesAlreadyInstalled($o->{packages}, $o->{prefix});
if ($rebuild_needed) {
$w->set(N("Finding packages to upgrade..."));
pkgs::selectPackagesToUpgrade($o->{packages}, $o->{prefix});
}
}
#------------------------------------------------------------------------------
sub choosePackages {
my ($o, $packages, $compssUsers, $_first_time) = @_;
#- this is done at the very beginning to take into account
#- selection of CD by user if using a cdrom.
$o->chooseCD($packages) if $o->{method} eq 'cdrom' && !$::oem;
my $w = $o->wait_message('', N("Looking for available packages..."));
my $availableC = &install_steps::choosePackages;
my $individual;
require pkgs;
my $min_size = pkgs::selectedSize($packages);
unless ($min_size < $availableC) {
$w = undef;
$o->ask_warn('', N("Your system does not have enough space left for installation or upgrade (%d > %d)",
$min_size, $availableC));
install_steps::rebootNeeded($o);
}
my $min_mark = 4;
my $b = pkgs::saveSelected($packages);
my $_level = pkgs::setSelectedFromCompssList($packages, { map { $_ => 1 } map { @{$compssUsers->{$_}{flags}} } @{$o->{compssUsersSorted}} }, $min_mark, 0);
my $max_size = pkgs::selectedSize($packages) + 1; #- avoid division by zero.
log::l("max size (level $min_mark) is : " . formatXiB($max_size));
pkgs::restoreSelected($b);
$w = undef;
chooseGroups:
$o->chooseGroups($packages, $compssUsers, $min_mark, \$individual, $max_size) if !$o->{isUpgrade} && !$::corporate && $o->{meta_class} ne 'desktop';
($o->{packages_}{ind}) =
pkgs::setSelectedFromCompssList($packages, $o->{compssUsersChoice}, $min_mark, $availableC);
$o->choosePackagesTree($packages) or goto chooseGroups if $individual;
install_any::warnAboutRemovedPackages($o, $o->{packages});
install_any::warnAboutNaughtyServers($o) or goto chooseGroups if !$o->{isUpgrade};
}
sub choosePackagesTree {
my ($o, $packages, $limit_to_medium) = @_;
$o->ask_many_from_list('', N("Choose the packages you want to install"),
{
list => [ grep { !$limit_to_medium || pkgs::packageMedium($packages, $_) == $limit_to_medium }
@{$packages->{depslist}} ],
value => \&URPM::Package::flag_selected,
label => \&URPM::Package::name,
sort => 1,
});
}
sub loadSavePackagesOnFloppy {
my ($o, $packages) = @_;
$o->ask_from('',
N("Please choose load or save package selection on floppy.
The format is the same as auto_install generated floppies."),
[ { val => \ (my $choice), list => [ N_("Load from floppy"), N_("Save on floppy") ], format => \&translate, type => 'list' } ]) or return;
if ($choice eq 'Load from floppy') {
while (1) {
my $w = $o->wait_message(N("Package selection"), N("Loading from floppy"));
log::l("load package selection from floppy");
my $O = eval { install_any::loadO(undef, 'floppy') };
if ($@) {
$w = undef; #- close wait message.
$o->ask_okcancel('', N("Insert a floppy containing package selection"))
or return;
} else {
install_any::unselectMostPackages($o);
foreach (@{$O->{default_packages} || []}) {
my $pkg = pkgs::packageByName($packages, $_);
pkgs::selectPackage($packages, $pkg) if $pkg;
}
return 1;
}
}
} else {
log::l("save package selection to floppy");
install_any::g_default_packages($o, 'quiet');
}
}
sub chooseGroups {
my ($o, $packages, $compssUsers, $min_level, $individual, $max_size) = @_;
#- for all groups available, determine package which belongs to each one.
#- this will enable getting the size of each groups more quickly due to
#- limitation of current implementation.
#- use an empty state for each one (no flag update should be propagated).
#- OLD VERSION
my $b = pkgs::saveSelected($packages);
install_any::unselectMostPackages($o);
pkgs::setSelectedFromCompssList($packages, {}, $min_level, $max_size);
my $system_size = pkgs::selectedSize($packages);
my ($sizes, $pkgs) = pkgs::computeGroupSize($packages, $min_level);
pkgs::restoreSelected($b);
log::l("system_size: $system_size");
my @groups = @{$o->{compssUsersSorted}};
my %stable_flags = grep_each { $::b } %{$o->{compssUsersChoice}};
delete $stable_flags{$_} foreach map { @{$compssUsers->{$_}{flags}} } @groups;
my $compute_size = sub {
my %pkgs;
my %flags = %stable_flags; @flags{@_} = ();
my $total_size;
A: while (my ($k, $size) = each %$sizes) {
Or: foreach (split "\t", $k) {
foreach (split "&&") {
exists $flags{$_} or next Or;
}
$total_size += $size;
$pkgs{$_} = 1 foreach @{$pkgs->{$k}};
next A;
}
}
log::l("computed size $total_size");
log::l("chooseGroups: ", join(" ", sort keys %pkgs));
int $total_size;
};
my %val = map {
$_ => every { $o->{compssUsersChoice}{$_} } @{$compssUsers->{$_}{flags}}
} @groups;
# @groups = grep { $size{$_} = round_down($size{$_} / sqr(1024), 10) } @groups; #- don't display the empty or small one (eg: because all packages are below $min_level)
my ($size, $unselect_all);
my $available_size = install_any::getAvailableSpace($o) / sqr(1024);
my $size_to_display = sub {
my $lsize = $system_size + $compute_size->(map { @{$compssUsers->{$_}{flags}} } grep { $val{$_} } @groups);
#- if a profile is deselected, deselect everything (easier than deselecting the profile packages)
$unselect_all ||= $size > $lsize;
$size = $lsize;
N("Total size: %d / %d MB", pkgs::correctSize($size / sqr(1024)), $available_size);
};
while (1) {
if ($available_size < 140) {
# too small to choose anything. Defaulting to no group chosen
$val{$_} = 0 foreach %val;
last;
}
$o->reallyChooseGroups($size_to_display, $individual, \%val) or return;
last if $::testing || pkgs::correctSize($size / sqr(1024)) < $available_size;
$o->ask_warn('', N("Selected size is larger than available space"));
}
$o->{compssUsersChoice}{$_} = 0 foreach map { @{$compssUsers->{$_}{flags}} } grep { !$val{$_} } keys %val;
$o->{compssUsersChoice}{$_} = 1 foreach map { @{$compssUsers->{$_}{flags}} } grep { $val{$_} } keys %val;
log::l("compssUsersChoice: " . (!$val{$_} && "not ") . "selected [$_] as [$o->{compssUsers}{$_}{label}]") foreach keys %val;
#- do not try to deselect package (by default no groups are selected).
$o->{isUpgrade} or $unselect_all and install_any::unselectMostPackages($o);
#- if no group have been chosen, ask for using base system only, or no X, or normal.
if (!$o->{isUpgrade} && !any { $_ } values %val) {
my $docs = !$o->{excludedocs};
my $minimal = !any { $_ } values %{$o->{compssUsersChoice}};
$o->ask_from(N("Type of install"),
N("You haven't selected any group of packages.
Please choose the minimal installation you want:"),
[
{ val => \$o->{compssUsersChoice}{X}, type => 'bool', text => N("With X"), disabled => sub { $minimal } },
{ val => \$docs, type => 'bool', text => N("With basic documentation (recommended!)"), disabled => sub { $minimal } },
{ val => \$minimal, type => 'bool', text => N("Truly minimal install (especially no urpmi)") },
],
changed => sub { $o->{compssUsersChoice}{X} = $docs = 0 if $minimal },
) or return &chooseGroups;
$o->{excludedocs} = !$docs || $minimal;
#- reselect according to user selection.
if ($minimal) {
$o->{compssUsersChoice}{$_} = 0 foreach keys %{$o->{compssUsersChoice}};
} else {
my $X = $o->{compssUsersChoice}{X}; #- don't let setDefaultPackages modify this one
install_any::setDefaultPackages($o, 'clean');
$o->{compssUsersChoice}{X} = $X;
}
install_any::unselectMostPackages($o);
}
1;
}
sub reallyChooseGroups {
my ($o, $size_to_display, $individual, $val) = @_;
my $size_text = &$size_to_display;
my ($path, $all);
$o->ask_from_({ messages => N("Package Group Selection"),
interactive_help_id => 'choosePackages',
callbacks => { changed => sub { $size_text = &$size_to_display } },
}, [
{ val => \$size_text, type => 'label' }, {},
(map {
my $old = $path;
$path = $o->{compssUsers}{$_}{path};
if_($old ne $path, { val => translate($path) }),
{
val => \$val->{$_},
type => 'bool',
disabled => sub { $all },
text => translate($o->{compssUsers}{$_}{label}),
help => translate($o->{compssUsers}{$_}{descr}),
}
} @{$o->{compssUsersSorted}}),
if_($o->{meta_class} eq 'desktop', { text => N("All"), val => \$all, type => 'bool' }),
if_($individual, { text => N("Individual package selection"), val => $individual, advanced => 1, type => 'bool' }),
]);
if ($all) {
$val->{$_} = 1 foreach keys %$val;
}
1;
}
sub chooseCD {
my ($o, $packages) = @_;
my @mediums = grep { $_ != $install_any::boot_medium } pkgs::allMediums($packages);
my @mediumsDescr;
my %mediumsDescr;
if (!common::usingRamdisk()) {
#- mono-cd in case of no ramdisk
foreach (@mediums) {
pkgs::mediumDescr($packages, $install_any::boot_medium) eq pkgs::mediumDescr($packages, $_) and next;
undef $packages->{mediums}{$_}{selected};
}
log::l("low memory install, using single CD installation (as it is not ejectable)");
return;
}
#- the boot medium is already selected.
$mediumsDescr{pkgs::mediumDescr($packages, $install_any::boot_medium)} = 1;
#- build mediumDescr according to mediums, this avoid asking multiple times
#- all the medium grouped together on only one CD.
foreach (@mediums) {
my $descr = pkgs::mediumDescr($packages, $_);
$packages->{mediums}{$_}{ignored} and next;
exists $mediumsDescr{$descr} or push @mediumsDescr, $descr;
$mediumsDescr{$descr} ||= $packages->{mediums}{$_}{selected};
}
#- if no other medium available or a poor beginner, we are choosing for him!
#- note first CD is always selected and should not be unselected!
return if @mediumsDescr == () || !$::expert;
# $o->set_help('chooseCD');
$o->ask_many_from_list('',
N("If you have all the CDs in the list below, click Ok.
If you have none of those CDs, click Cancel.
If only some CDs are missing, unselect them, then click Ok."),
{
list => \@mediumsDescr,
label => sub { N("Cd-Rom labeled \"%s\"", $_[0]) },
val => sub { \$mediumsDescr{$_[0]} },
}) or do {
$mediumsDescr{$_} = 0 foreach @mediumsDescr; #- force unselection of other CDs.
};
#- restore true selection of medium (which may have been grouped together)
foreach (@mediums) {
my $descr = pkgs::mediumDescr($packages, $_);
$packages->{mediums}{$_}{ignored} and next;
$packages->{mediums}{$_}{selected} = $mediumsDescr{$descr};
log::l("select status of medium $_ is $packages->{mediums}{$_}{selected}");
}
}
#------------------------------------------------------------------------------
sub installPackages {
my ($o, $packages) = @_;
my ($current, $total) = (0, 0);
my $w = $o->wait_message(N("Installing"), N("Preparing installation"));
my $old = \&pkgs::installCallback;
local *pkgs::installCallback = sub {
my ($data, $type, $id, $subtype, $_amount, $total_) = @_;
if ($type eq 'user' && $subtype eq 'install') {
$total = $total_;
} elsif ($type eq 'inst' && $subtype eq 'start') {
my $p = $data->{depslist}[$id];
$w->set(N("Installing package %s\n%d%%", $p->name, $total && 100 * $current / $total));
$current += $p->size;
} else { goto $old }
};
#- the modification is not local as the box should be living for other package installation.
#- BEWARE this is somewhat duplicated (but not exactly from gtk code).
undef *install_any::changeMedium;
*install_any::changeMedium = sub {
my ($method, $medium) = @_;
#- if not using a cdrom medium, always abort.
$method eq 'cdrom' && !$::oem and do {
my $name = pkgs::mediumDescr($o->{packages}, $medium);
local $| = 1; print "\a";
my $r = $name !~ /commercial/i || ($o->{useless_thing_accepted2} ||= $o->ask_from_list_('', formatAlaTeX(install_messages::com_license()), [ N_("Accept"), N_("Refuse") ], "Accept") eq "Accept");
$r &&= $o->ask_okcancel('', N("Change your Cd-Rom!
Please insert the Cd-Rom labelled \"%s\" in your drive and press Ok when done.
If you don't have it, press Cancel to avoid installation from this Cd-Rom.", $name), 1);
return $r;
};
};
my $install_result;
catch_cdie { $install_result = $o->install_steps::installPackages($packages) }
sub {
if ($@ =~ /^error ordering package list: (.*)/) {
$o->ask_yesorno('', [
N("There was an error ordering packages:"), $1, N("Go on anyway?") ], 1) and return 1;
${$_[0]} = "already displayed";
} elsif ($@ =~ /^error installing package list: (.*)/) {
$o->ask_yesorno('', [
N("There was an error installing packages:"), $1, N("Go on anyway?") ], 1) and return 1;
${$_[0]} = "already displayed";
}
0;
};
if ($pkgs::cancel_install) {
$pkgs::cancel_install = 0;
die "setstep choosePackages\n";
}
$install_result;
}
sub afterInstallPackages($) {
my ($o) = @_;
my $_w = $o->wait_message('', N("Post-install configuration"));
$o->SUPER::afterInstallPackages;
}
sub copyKernelFromFloppy {
my ($o) = @_;
$o->ask_okcancel('', N("Please insert the Boot floppy used in drive %s", $o->{blank}), 1) or return;
$o->SUPER::copyKernelFromFloppy;
}
sub updateModulesFromFloppy {
my ($o) = @_;
$o->ask_okcancel('', N("Please insert the Update Modules floppy in drive %s", $o->{updatemodules}), 1) or return;
$o->SUPER::updateModulesFromFloppy;
}
#------------------------------------------------------------------------------
sub configureNetwork {
my ($o) = @_;
require network::network;
network::network::easy_dhcp($o->{netc}, $o->{intf}) and $o->{netcnx}{type} = 'lan';
$o->SUPER::configureNetwork;
}
#------------------------------------------------------------------------------
sub installUpdates {
my ($o) = @_;
my $u = $o->{updates} ||= {};
$o->hasNetwork or return;
is_empty_hash_ref($u) and $o->ask_yesorno_({ messages => formatAlaTeX(
N("You now have the opportunity to download updated packages. These packages
have been updated after the distribution was released. They may
contain security or bug fixes.
To download these packages, you will need to have a working Internet
connection.
Do you want to install the updates ?")),
interactive_help_id => 'installUpdates',
}) || return;
#- bring all interface up for installing crypto packages.
install_interactive::upNetwork($o);
#- update medium available and working.
my $update_medium;
do {
require crypto;
eval {
my @mirrors = do {
my $_w = $o->wait_message('', N("Contacting Mandrake Linux web site to get the list of available mirrors..."));
crypto::mirrors() };
#- if no mirror have been found, use current time zone and propose among available.
$u->{mirror} ||= crypto::bestMirror($o->{timezone}{timezone});
$o->ask_from_({ messages => N("Choose a mirror from which to get the packages"),
cancel => N("Cancel"),
}, [ { separator => '|',
format => \&crypto::mirror2text,
list => \@mirrors,
val => \$u->{mirror},
},
],
) or $u->{mirror} = '';
};
return if $@ || !$u->{mirror};
eval {
if ($u->{mirror}) {
my $_w = $o->wait_message('', N("Contacting the mirror to get the list of available packages..."));
$update_medium = crypto::getPackages($o->{prefix}, $o->{packages}, $u->{mirror});
}
};
} while $@ || !$update_medium && $o->ask_yesorno('', N("Unable to contact mirror %s", $u->{mirror}) . ($@ ? " :\n$@" : "") . "\n\n" . N("Would you like to try again?"));
if ($update_medium) {
if ($o->choosePackagesTree($o->{packages}, $update_medium)) {
$o->{isUpgrade} = 1; #- now force upgrade mode, else update will be installed instead of upgraded.
$o->pkg_install;
} else {
#- make sure to not try to install the packages (which are automatically selected by getPackage above).
#- this is possible by deselecting the medium (which can be re-selected above).
delete $update_medium->{selected};
}
#- update urpmi even, because there is an hdlist available and everything is good,
#- this will allow user to update the medium but update his machine later.
$o->install_urpmi;
}
#- stop interface using ppp only. FIXME REALLY TOCHECK isdn (costly network) ?
# FIXME damien install_interactive::downNetwork($o, 'pppOnly');
}
#------------------------------------------------------------------------------
sub configureTimezone {
my ($o, $clicked) = @_;
require timezone;
$o->{timezone}{timezone} = $o->ask_from_treelist('', N("Which is your timezone?"), '/', [ timezone::getTimeZones($::g_auto_install ? '' : $o->{prefix}) ], $o->{timezone}{timezone}) || return;
my $ntp = to_bool($o->{timezone}{ntp});
$o->ask_from_({ interactive_help_id => 'configureTimezoneGMT' }, [
{ text => N("Hardware clock set to GMT"), val => \$o->{timezone}{UTC}, type => 'bool' },
{ text => N("Automatic time synchronization (using NTP)"), val => \$ntp, type => 'bool' },
]) or goto &configureTimezone
if $::expert || $clicked;
if ($ntp) {
my $servers = timezone::ntp_servers();
$o->{timezone}{ntp} ||= 'pool.ntp.org';
$o->ask_from_({},
[ { label => N("NTP Server"), val => \$o->{timezone}{ntp}, list => [ keys %$servers ], not_edit => 0,
format => sub { $servers->{$_[0]} ? "$servers->{$_[0]} ($_[0])" : $_[0] } } ]
) or goto &configureTimezone;
} else {
$o->{timezone}{ntp} = '';
}
install_steps::configureTimezone($o);
1;
}
#------------------------------------------------------------------------------
sub configureServices {
my ($o, $clicked) = @_;
require services;
$o->{services} = services::ask($o) if $::expert || $clicked;
install_steps::configureServices($o);
}
sub summaryBefore {
my ($o) = @_;
#- auto-detection
$o->configurePrinter(0);
install_any::preConfigureTimezone($o);
#- get back network configuration.
require network::network;
eval {
network::network::read_all_conf($o->{prefix}, $o->{netc} ||= {}, $o->{intf} ||= {}, $o->{netcnx} ||= {});
};
log::l("summaryBefore: network configuration: ", formatError($@));
}
sub summary_prompt {
my ($o, $l, $check_complete) = @_;
foreach (@$l) {
my $val = $_->{val};
($_->{format}, $_->{val}) = (sub { $val->() || N("not configured") }, '');
}
$o->ask_from_({
messages => N("Summary"),
interactive_help_id => 'summary',
cancel => '',
callbacks => { complete => sub { !$check_complete->() } },
}, $l);
}
sub summary {
my ($o) = @_;
my @l;
push @l, {
group => N("System"),
label => N("Keyboard"),
val => sub { $o->{keyboard} && translate(keyboard::keyboard2text($o->{keyboard})) },
clicked => sub { $o->selectKeyboard(1) },
};
my $timezone_manually_set;
push @l, {
group => N("System"),
label => N("Country / Region"),
val => sub { lang::c2name($o->{locale}{country}) },
clicked => sub {
any::selectCountry($o, $o->{locale}) or return;
$o->do_pkgs->install('locales-' . substr(lang::getlocale_for_country($o->{locale}{lang}, $o->{locale}{country}), 0, 2));
lang::write($o->{prefix}, $o->{locale});
if (!$timezone_manually_set) {
delete $o->{timezone};
install_any::preConfigureTimezone($o); #- now we can precise the timezone thanks to the country
}
},
};
push @l, {
group => N("System"),
label => N("Timezone"),
val => sub { $o->{timezone}{timezone} },
clicked => sub { $timezone_manually_set = $o->configureTimezone(1) || $timezone_manually_set },
};
push @l, {
group => N("System"),
label => N("Mouse"),
val => sub { translate($o->{mouse}{type}) . ' ' . translate($o->{mouse}{name}) },
clicked => sub { $o->selectMouse(1); mouse::write($o, $o->{mouse}) },
};
push @l, {
group => N("Hardware"),
label => N("Printer"),
val => sub {
if (is_empty_hash_ref($o->{printer}{configured})) {
require pkgs;
my $p = pkgs::packageByName($o->{packages}, 'cups');
$p && $p->flag_installed ? N("Remote CUPS server") : N("No printer");
} elsif (defined($o->{printer}{configured}{$o->{printer}{DEFAULT}}) &&
(my $p = find { $_ && ($_->{make} || $_->{model}) }
$o->{printer}{configured}{$o->{printer}{DEFAULT}}{queuedata})) {
"$p->{make} $p->{model}";
} elsif ($p = find { $_ && ($_->{make} || $_->{model}) }
map { $_->{queuedata} } (values %{$o->{printer}{configured}})) {
"$p->{make} $p->{model}";
} else {
N("Remote CUPS server"); #- fall back in case of something wrong.
}
},
clicked => sub { $o->configurePrinter(1) },
};
my @sound_cards = detect_devices::getSoundDevices();
my $sound_index = 0;
foreach my $device (@sound_cards) {
$device->{sound_slot_index} = $sound_index;
push @l, {
group => N("Hardware"),
label => N("Sound card"),
val => sub {
$device->{driver} && modules::module2description($device->{driver}) || $device->{description};
},
clicked => sub {
require harddrake::sound;
harddrake::sound::config($o, $device);
},
};
$sound_index++;
}
if (!@sound_cards && ($o->{compssUsersChoice}{GAMES} || $o->{compssUsersChoice}{AUDIO})) {
#- if no sound card are detected AND the user selected things needing a sound card,
#- propose a special case for ISA cards
push @l, {
group => N("Hardware"),
label => N("Sound card"),
val => sub {},
clicked => sub {
if ($o->ask_yesorno('', N("Do you have an ISA sound card?"))) {
$o->do_pkgs->install('sndconfig');
$o->ask_warn('', N("Run \"sndconfig\" after installation to configure your sound card"));
} else {
$o->ask_warn('', N("No sound card detected. Try \"harddrake\" after installation"));
}
},
};
}
foreach my $tv (detect_devices::getTVcards()) {
push @l, {
group => N("Hardware"),
label => N("TV card"),
val => sub { $tv->{description} },
clicked => sub {
require harddrake::v4l;
harddrake::v4l::config($o, $tv->{driver});
}
};
}
push @l, {
group => N("Hardware"),
label => N("Graphical interface"),
val => sub { $o->{raw_X} ? Xconfig::various::to_string($o->{raw_X}) : '' },
clicked => sub { configureX($o, 'expert') },
};
push @l, {
group => N("Network & Internet"),
label => N("Network"),
val => sub { $o->{netcnx}{type} },
clicked => sub {
local $::expert = $::expert;
require network::netconnect;
network::netconnect::main($o->{prefix}, $o->{netcnx} ||= {}, $o, $o->{netc}, $o->{mouse}, $o->{intf}, 0, 1);
#- in case netcnx type is not updated.
require network::network;
network::network::probe_netcnx_type($o->{prefix}, $o->{netc}, $o->{intf}, $o->{netcnx});
},
};
push @l, {
group => N("Security"),
label => N("Security Level"),
val => sub {
require security::level;
security::level::to_string($o->{security});
},
clicked => sub {
require security::level;
security::level::level_choose($o, \$o->{security}, \$o->{libsafe}, \$o->{security_user})
and install_any::set_security($o);
},
};
push @l, {
group => N("Security"),
label => N("Firewall"),
val => sub {
require network::shorewall;
my $shorewall = network::shorewall::read();
$shorewall && !$shorewall->{disabled} ? N("activated") : N("disabled");
},
clicked => sub {
require network::drakfirewall;
network::drakfirewall::main($o, $o->{security} <= 3);
},
} if detect_devices::getNet();
push @l, {
group => N("Boot"),
label => N("Bootloader"),
val => sub {
#-PO: example: lilo-graphic on /dev/hda1
N("%s on %s", $o->{bootloader}{method}, $o->{bootloader}{boot})
},
clicked => sub { any::setupBootloader($o, $o->{bootloader}, $o->{all_hds}, $o->{fstab}, $o->{security}) },
};
push @l, {
group => N("System"),
label => N("Services"),
val => sub {
require services;
my ($l, $activated) = services::services();
N("Services: %d activated for %d registered", int(@$activated), int(@$l));
},
clicked => sub {
require services;
$o->{services} = services::ask($o) and services::doit($o, $o->{services});
},
};
my $check_complete = sub {
$o->{raw_X} || !pkgs::packageByName($o->{packages}, 'XFree86')->flag_installed ||
$o->ask_yesorno('', N("You have not configured X. Are you sure you really want this?"));
};