О блоге

Все новые материалы размещаются на Блогосайте alv.me. Старые - в процессе переноса.

26.07.2008

FreeBSD: syscons по русски

2004 г

Содержание

Вступление

Возможность простой и корректной работы с языками, отличными от американского английского (конкретно, в наших условиях, русским) - одно из необходимых условий настольного использования любой операционной системы. И большинство распространенных юзерофильных дистрибутивов Linux давно уже, вне зависимости от ПМЖ разработчиков, заговорили по-русски "из коробки".

Однако мир свободных ОС не замкнулся на Linux'е - существует еще и их BSD-семейство. И пользователь вправе задаться вопросом - а как в нем обстоит дело с русификацией?

На это я вынужден ответить честно и откровенно: по разному. Так, в NetBSD и OpenBSD до недавнего времени с русификацией возникали определенные проблемы (хотя нынче они постепенно уходят в прошлое). А вот FreeBSD в этом отношении выглядят ничуть не хуже, чем любые дистрибутивы Linux, даже отечественного производства. Ибо в ней можно выполнить полную русификацию уже на стадии начальной установки, не покидая программы sysinstall (посредством которой русификация может быть произведена и в любой другой момент времени).

Теория и практика русификации подробно рассмотрена в известном мемуаре Ивана Паскаля и описана также в моей книжке. Поэтому затрону только те моменты, которые появились в новых версиях, а также оказались не затронутыми ранее. Причем речь пойдет только о русификации текстового режима, то есть драйвера syscons, - русификация Иксов есть предмет отдельного разговора, с FreeBSD прямо не связанного.

Базовая русификация средствами sysinstall

Для русификации FreeBSD 5-й ветки достаточно при установке (или позднее - запустив sysinstall из командной строки) зайти в меню Configuration и выбрать там пункт Console. В нас заинтересуют следующие подпункты:

  • Font;
  • Keymap;
  • Screenmap;
  • Ttys.

В пункте Font выбирается шрифт для экранного вывода. Для нас интерес пресдтавляют следующие варианты - шрифты IBM 866 или (для обитателей моей исторической родины) IBM 866u, обеспечивающие вывод в кодировке DOS, а также (для бывших "подоконников") IBM 1251, позволяющий вывод в кодировке Windows (должен только предупредить, что нет ничего более уродливого, чем вид консольных программ, использующих псевдографику, типа Midnight Commander, при использовании экранного вывода в Windows-кодировке). Вывод в кодировке KOI8 также возможен, но потребует некоторых дополнительных действий руками, о которых будет сказано ниже.

Традиционным для FreeBSD (впрочем, как и для Linux) является экранный вывод в DOS-кодировке, на причинах чего задерживаться я не буду. Так что на нем для начала и остановимся. А вот раскладку клавиатуры, выбираемую в подпункте Keymap, мы установим для кодировки KOI8-R; впрочем, другой в sysinstall не предусмотрено. Что, однако, не запрещает использовать для ввода и DOS- или Windows-кодировку - соответствующие раскладки в комплекте имеются, только устанавливать их придется вручную.

На резонный вопрос о различии кодировок ввода и вывода мы ответим подпунктом Screenmap, в котором устанавливаются карты соответствия между оными. В нашем случае таковой будут KOI8-R to IBM866 или (для граждан незалежной Украины) KOI8-U to IBM866u. Очевидно, что при использовании DOS-кодировки и для ввода, и для вывода необходимости в карте соответствия нет, а при Windows-выводе карту соответствия придется руками не только установить, но и предварительно скачать - откуда, см. заключение.

Наконец, остается последнее действие - изменение типа терминала, без чего экранный вывод, особенно псевдографики, будет выглядеть, скажем так, несколько странно. Это осуществляется в подпункте Ttys. Здесь следует выбрать KOI8-R (терминал cons25r) для России или KOI8-U (терминал cons25u) для Украины. И на этом успокоится - по завершении установки (или реконфигурирования) системы и перезагрузке мешины мы будем иметь базовые средства для работы с кириллицей.

Результат стандартной русификации

Метод русификации через sysinstall прост, но имеет некоторые ограничения. Во-первых, устанавливаемая при этом кириллическая раскладка клавиатуры весьма необычна, соответствуя примерно DOS-маркировке клавиш, но со знаками препинания на нижнем регистре, а цифрами - на верхнем. Само по себе это удобно (точки и запятые приходится вводить чаще, чем цифирь, для которой еще и KeyPad имеется), однако для большинства пользователей непривычно. Во-вторых, умолчальный экранный шрифт далек от эстетического совершенства, особенно в кириллической части. В третьих, практически единственные возможные при этом кодировки - KOI8-R для ввода и DOS - для вывода. И, наконец, в четвертых, устанавливаемый через sysinstall тип терминала предназначен только для стандартного экранного разрешения (вернее, плотности символов) - 25 строк на 80 колонок.

Так что вполне возможно, что появится желание изменить некторые (или все) из установленных параметров. Чтобы понять, как это сделать, посмотрим, как наши интерактивные действия отразились в конфигурационных файлах FreeBSD. А отразились они в файлах /etc/rc.conf и /etc/ttys. В первом посредством sysinstall были добавлены строки

font8x14="cp866-8x14"
font8x16="cp866b-8x16"
font8x8="cp866-8x8"

отвечающие за загрузку шрифтов для разных экранных разрешений (вернее, разного количества строк), строка

keymap="ru.koi8-r.kbd"

загружающая кириллическую раскладку клавиатуры, и строка

scrnmap="koi8-r2cp866"

обеспечивающая перекодировку KOI8-ввода в DOS-вывод (в предположении, что все делалось в соответствие с традициями и рекомендациями).

Что дают эти строки? Для понимания этого нужно сделать несколько дополнительных замечаний. Как известно, во управление экраном и клавиатуров во FreeBSD... Вернее, в syscons - драйвере системной консоли, используемой в этой ОС по умолчанию; возможно также использование в этом качестве драйвера pcvt (весьма скверно русифицируемого, однако единственно работающего, как говорят, на некоторых старых ноутбуках).

...Так вот, для управления экраном (в том числе шрифтами) и клавиатурой (в том числе раскладками) в syscons используется две программы - vidcontrol и kbdcontrol, соответственно. Первая, как нетрудно догадаться, отвечает за экран, в том числе с помощью опции -f font_name позволяет подгружать шрифты вывода, вторая - за клавиатуру, с помощью опции -l keymap_name позволяя загружать клавиатурные раскладки. Кроме того, команда vidcontrol c опцией -l screenmap_name обеспечивает, при необходимости, загрузку карты соответствия между кодировками ввода и вывода.

Команды vidcontrol и kbdcontrol для загрузки шрифта, раскладки и клавиатуры отрабатываются при старте системы (в сценарии /etc/rc.d/syscons). И параметры свои они получают при этом именно из значений соответствующих строк главного конфигурационного файла - /etc/rc.conf. Благодаря чему и осуществляется кириллизация системы при ее загрузке.

В файле /etc/ttys значения типа терминала изменились с умолчального cons25 на выбранный cons25r для всех виртуальных консолей (их всего по умолчанию 8).

Очевидно, что для изменения шрифта, раскладки, карты соответствия и типа терминала достаточно изменить соответствующие значения в перечисленных файлах. Нужно только знать, какие из этих значений допустимы.

Что и как менять

Начнем с типа терминала. Все возможные их варианты описаны в файле /etc/termcap (вернее, /usr/share/misc/termcap, на который он ссылается). Для русифицированного в кодировке KOI8 терминала можно увидеть несколько значений - от стандартного cons25r до максимально плотного cons60r (очевидно, что число соответствует плотности строк). То есть при использовании нестандартных экранных разрешений нужно заменить в /etc/ttys умолчальные значения типа терминала на те, которые соответствуют установленному числу строк. При использовании иных кодировок или разрешений, возможно, придется внести описания соответствующих им типов терминалов вручную. Хотя это и не приветствуется - судя по тому, что файл /usr/share/misc/termcap по умолчанию закрыт для изменений даже суперпользователю.

Теперь - возможные раскладки клавиатуры. Файлы описания оных находятся в каталоге /usr/share/syscons/keymaps и кириллическая его часть выглядит следующим образом:

ru.cp866.kbd
ru.iso5.kbd
ru.koi8-r.kbd
ru.koi8-r.shift.kbd

Практически, однако, кроме умолчальной раскладки ru.koi8-r.kbd, интерес представляет только последний файл - это обычная раскладка для старых клавиатур с DOS-маркировкой. Однако в продаже нынче таких уже не найти. И потому хорошо бы иметь раскладку в кодировке KOI8 для Windows-маркированных клавиатур, использующую и дополнительные Win-клавиши. Изготовить таковую самостоятельно - большого труда не составит - формат файлов клавиатурных раскладок предельно прозрачен (детали - см. у Ивана Паскаля). Однако если это лениво - такая работа уже проделана, о чем я скажу в заключении.

Обращаемся к шрифтам. Их, содержащих символы кириллицы, немало в каталоге /usr/src/share/syscons/fonts:

cp1251-8x14.fnt
cp1251-8x16.fnt
cp1251-8x8.fnt

для Windows-кодировки,

cp866-8x14.fnt
cp866-8x16.fnt
cp866-8x8.fnt
cp866b-8x16.fnt
cp866c-8x16.fnt
cp866u-8x14.fnt
cp866u-8x16.fnt
cp866u-8x8.fnt

для кодировки DOS,

koi8-r-8x14.fnt
koi8-r-8x16.fnt
koi8-r-8x8.fnt
koi8-rb-8x16.fnt
koi8-rc-8x16.fnt
koi8-u-8x14.fnt
koi8-u-8x16.fnt
koi8-u-8x8.fnt

для кодировки KOI8. Есть даже шрифты для ISO 8859-5:

iso05-8x14.fnt
iso05-8x16.fnt
iso05-8x8.fnt

Опять же, практически интересными выглядят только шрифты для CP866 и KOI8. И тут пользователя постигает изрядное разочарование: ни одно из предложенных в комплекте начертаний нельзя, мягко говоря, назвать шедевром фонт-дизайнерской мысли. Возникает резонный вопрос - можно ли пополнить коллекцию, и если да - то как?

Пополнение коллекции шрифтов

В любой дистрибутив Linux отечественного (а в последнее время - и не только отечественного) производства входит достаточно большой набор кириллических шрифтов для консоли, среди которых есть очень даже приятные для глаз - UniCyr-lenta и UniCyr-sans, а также разнообразные стилизации с элементами декоративности - alt-antiq, alt-asian, alt-t. Однако напрямую прикрутить их к консоли FreeBSD не удастся - все они в psf-формате,содержащем всякого рода дополнительную информацию (заголовки и т.н. psf-сигнатуры), тогда как во FreeBSD используются либо шрифты в raw-формате, не содержащие ничего, кроме собственно бинарных данных о шрифте. Точнее, собственно Free'шные шрифты имеют еще и некое минимальное обрамление - его можно видеть, дав команду

$ ls path_to/font_name

Однако чистые raw-шрифты также можно спокойно использовать. И получить их из шрифтов psf достаточно просто: достаточно отсечь от последних заголовочную часть (размером 4 байта) и сигнатуру, вычленив таким образом собственно бинарное описание. Размер последнего составляет 4096, 3584 или 2048 байт (для шрифтов с матрицами 8x16, 8x14 и 8x8, соответственно). Проделать такую процедуру можно командой dd с соответствующими параметрами. Для шрифта с матрицей 8x16, скажем, того же UniCyr-sans, она будет выглядеть следующим образом:

$ dd if=UniCyr-sans-8x16.psf \
of=UniCyr-sans-8x16.fnt \
bs=1 skip=4 count=4096

Если Linux-шрифт, как это обычно бывает в дистрибутивах, предствален в gzip-сжатом виде, его предварительно нужно распаковать.

Таким образом мы получем достаточное количество шрифтов хорошего качества. Единственное для них ограничение - они не могут быть вкомпилированы в ядро FreeBSD, на это способны только шрифты в ее собственном формате.

Однако это еще не все - существует пакет terminus-fonts, включающий в себя консольные и терминальные (для X-терминалов) шрифты на все случаи жизни, а также инструменты для их генерации. Он столь замечателен, что заслуживает подробного рассмотрения.

Шрифтовой терминатор

Пакет terminus-fonts - болгарского происхождения и проживает здесь в виде архива tar.gz объемом около 100 Кбайт. Имеется он и портах FreeBSD (x11-fonts/terminus-font), а также доступен для нее в качестве бинарного пакета. Хотя я лично предпочел бы устанавливать его вручную, как описано ниже - и порт, и пакет содержат только терминальную (для X-терминалов) часть оригинального набора.

Как уже было отмечено, terminus-fonts - не просто шрифтовой набор, а универсальный инструмент для генерации терминальных шрифтов любого назначения. Он включает в себя

  • шрифтовые файлы базовой гарнитуры в формате BDF (Bitmap Distribution Format) нормального и полужирного начертания, высотой от 14 до 24 пикселей, в кодировке Unicode;
  • набор скриптов для преобразования их в шрифтовые файлы различных используемых Unix-консолями и X-терминалами форматов;
  • make-файлы для соответствующих преобразований;
  • необходимые дополнительные данные, в частности, unimap-таблицы для преобразования 8-битных кодировок в Unicode;
  • файлы README-документации на английском и болгарском языках.

В README-файлах дается исчерпывающее описание того, как обращаться с пакетов. И потому я лишь кратко опишу доступные возможности. Итак, базовые bdf-шрифты могут быть преобразованы в шрифтовые файлы следующих форматов:

  • raw-формат, в котором шрифтовой файл содержит только бинарные данные; этот формат используется для вывода в консольных драйверах BSD-семейства (syscons FreeBSD, pcvt и wscons);
  • psf-формат, включающий, кроме собственно шрифтовых данных, заголовок и psf-сигнатуру с дополнительной информацией о шрифте; это - основной формат вывода в Linux-консоли;
  • pcf-формат для вывода на X-терминалах.

Генерация шрифтовых файлов осуществляется командой make с указанием соответствующей цели. Например, для получения интересующих нас в данный момент шрифтов для системной консоли FreeBSD (raw-файлов) она будет выглядеть так:

$ make raw

А шрифты для Linux-консоли и X-терминала получаются соответственно командами:

$ make psf

и

$ make pcf

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

В любом случае каждое шрифтоначертание автоматически генерируется в нескольких кодировках: ISO8859-1/2/5/9/15/16, Windows-1250/1251/1252/1254, IBM-437/852/855/866, KOI8-R/U/E/F, Bulgarian-MIK, Paratype-PT154/PT254 и Macintosh-Ukrainian.

Интересно, что для BSD-консоли шрифты с традиционной для нее кодировкой вывода CP866 сами собой не образуются. Однако их при можно изготовить из шрифтов Linux-консоли способом, аналогичным описанному в предыдущем разделе. Или - просто отказаться от ее использования, ограничившись выводом в KOI8. Ведь одна из причин применения DOS-кодировки на выводе - низкое качество KOI-шрифтов, - теперь отпадает, а с разрывами в рамках псевдографических программ я, например, вполне готов примириться... Правда, это требует еще некоторых действий (см. ниже).

Что использовать для вывода

Остается разобраться с картами соответствия - на что их стоит менять, и стоит ли вообще. При использовании для экранного вывода кодировки DOS ничего с ними делать не нужно, оставив соответствующую строку из /etc/rc.conf в неприкосновенности. Тем более, что никаких других карт соответствия в комплекте FreeBSD и нету. И, очевидно, что если вывод, как и ввод, осуществляется в кодировке KOI8, необходимость в карте соответствия вообще отпадает, так что строку

scrnmap="koi8-r2cp866"

нужно закомментировать или просто удалить.

Однако использование экранной кодировки KOI8, помимо некоторого искажения символов псевдографики, влечет за собой более неприятный эффект. Ибо коды символов, которыми представляется т.н. графический (точнее, конечно же, псевдографический) курсор консольной мыши, совпадают с KOI-кодами русских букв п, я, р, с. В результате чего при перемещении мыши буквы эти исчезают с экрана (хорошо еще, что не из файла:-)). Избежать этого можно, переопределив "мышиные" коды - одним из двух способов. Первый - включить в файл /etc/rc.conf строку

mousechar_start="3"

Второй - пересобрать ядро с опцией

options    SC_MOUSE_CHAR=0x3

Поскольку ядро все равно пересобирать - второй способ кажется предпочтительней. В любом случае после этого курсор мыши в сочетании с KOI8 не доставит никаких неприятностей.

Наконец, если есть настоятельная необходимость использовать в качестве системной кодировку CP1251, необходимо установить соответствующую раскладку клавиатуры и крату соответствия CP1251 -> CP866, потому что экранный вывод следует сохранить в DOS-кодировке: нет ничего более уродливого, чем вид программ, использующих псевдографику, в представлении Windows-кодировки.

Русификация на уровне ядра

Раз уж речь зашла о ядре, поговорим о принципиально ином способе русификации FreeBSD. Он предполагает, что раскладка клавиатуры и экранный шрифт с поддержкой кириллицы не подгружаются при страте системы с помощью соотвествующих опций командами vidcontrol и kbdcontrol, а встраиваются непосредственно в ядро взамен умолчальных англо-американских. Первое достигается включением в файл конфигурации ядра (/usr/src/sys/i386/conf/MYKERNEL) двух строк:

options         ATKBD_DFLT_KEYMAP

разрешающей встраивание клавиатурной раскладки, отличной от умолчальной, и

makeoptions     ATKBD_DFLT_KEYMAP=имя_раскладки

собственно и указывающей, какую раскладку следует встроить (например, ru.koi8-r.shift). Аналогично для встаривания экранного шрифта требуются строки

options         SC_DFLT_FONT

разрешающая переопределение шрифта, поддерживаемого по умолчанию, и

makeoptions     SC_DFLT_FONT=codepage

указывающая на требуемую кодировку (например, koi8-r). Правда, в файле /usr/src/sys/conf/NOTES, описывающем все возможные опции конфигурирования ядра, я не нашел никаких указаний на возможность встраивания в ядро карты соответствия. Так что ее все равно придется грузить через /etc/rc.conf (или - использовать одну и ту же кодировку и для ввода, и для вывода).

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

Локализация

Последнее действие, требующееся для корректной работы с русским языком - это определение locale, т.н. локализация. Во FreeBSD она может быть выполнена двояко. Первый способ - стандартный для всех POSIX-систем, через определение локально-зависимых переменных в профильном файле пользовательской оболочки (login shell). Он многократно описан, и задерживаться на нем я не буду.

Второй способ - специфичен, насколько я знаю, именно для FreeBSD. Дело в том, что в этой ОС учетная запись пользователя имеет, кроме обычных полей (имя, шелл и т.д.), еще и атрибут class. Он позволяет задать переменные окружения (в том числе и локально-зависимые) для данного пользователя глобально, вне зависимости от его пользовательской оболочки.

Все предопределенные классы пользователей описываются в файле /etc/login.conf. Просмотр его показывает, что среди них существует и класс russian. От "умолчального" (default) класса он отличается только значениями локально-зависимых переменных:

#
# Russian Users Accounts. Setup proper environment variables.
#
russian|Russian Users Accounts:\
:charset=KOI8-R:\
:lang=ru_RU.KOI8-R:\
:tc=default:

Прошу обратить внимание на строку :tc=default: - именно она и свидетельствует, что все остальные параметры берутся из описания класса default, скоро нам это может понадобиться.

Так что если локаль KOI8-R нас устраивает, все, что требуется - это приписать нужного пользователя к классу russian. Как? Опять же, возможны вариант. Например, при создании нового пользовательского аккаунта посредством утилиты adduser (а это - самый простой способ создать одного-двух пользователей домашнего десктопа: себя, любимого - для нормальной работы, и себя, любимого не менее, - для всякого рода нездоровых экспериментов) вопрос о классе пользователя будет задан явно.

Класс пользователя можно переопределить и позднее - любой соответствующей утилитой. Благо во FreeBSD есть могучая команда pw, - универсальный инструмент для управления учетными записями вообще. При ее посредстве это делается так:

$ pw usermod юзер_имя_рек -L russian

Если же KOI'шная локаль почему-либо не устраивает - придется создавать свой собственный класс пользователей. Хотя делается это просто - в файл /etc/login.conf вносится строка с именем класса и его описанием, затем даются нужные значения переменных charset и lang. Например, если требуется общение с "подоконниками", им можно присвоить значения

ruswin|Russian Win Accounts:\
:charset=CP1251:\
:lang=ru_RU.CP1251:\

не забыв добавить ту самую строку :tc=default:. К слову сказать, в текущей версии FreeBSD имеется полный набор русских локалей:

$ locale -a | grep ru                                      18:03 ttyp2
ru_RU.CP1251
ru_RU.CP866
ru_RU.ISO8859-5
ru_RU.KOI8-R

Можно видеть, что в приведенном списке локаль UFT-8 не наблюдается. И действительно, в штатном комплекте FreeBSD ее нет. Однако при желании несколько приблизиться к светлому будущему (недостижимому, как коммунизм в одной отдельно взятой стране) - ее можно установить из портов (/usr/ports/misc/utf8locale), после чего в выводе команды locale -a добавится строка ru_RU.UTF-8. Впрочем, этой теме посвящена специальная статья.

Заключение

Вот, собственно, и все. Хотя нет: помнится, я обещал сказать, как избавиться от необходимости самому конвертировать Linux'овые шрифты или создавать раскладки. Так вот, их можно скачать с этого сайта - полную коллекцию кириллических raw-шрифтов и win-раскладки для кодировок KOI8-R и CP1251. Есть там и карта соответствия для пары ввода/вывода CP1251 -> CP866.