Next Previous Contents

## 7. Как настроить - основы

Для общих конфигураций вам вероятно захочется проигнорировать этот раздел, вместо этого вы должны перейти к разделу о Решениях Производителей, или еще лучше к документации вашего поставщика. Большинство дистрибутивов Linux поставляет одну или несколько дуракоустойчивых утилит для того, чтобы делать все описанное здесь для основных типов принтеров.

Если предоставленные вам утилиты не подходят вам, или вы хотите контролировать настройки печати, то вы должны использовать PDQ; Я рекомендую использование PDQ в большинстве случаев.

## 7.1 Настройка PDQ

PDQ может быть настроен либо администратором, либо обычным пользователем. Изменения внесенные администратором делаются в файле /etc/printrc, и применяются ко всем пользователям, в то время как обычный пользователь может изменять только свой персональный файл .printrc. Все описанное применяется к обоим типам настройки.

Если PDQ не доступен в вашем дистрибутиве, то вы должны взять исходные тексты со страницы PDQ и скомпилировать его сами. Он легко компилируется, но вы сначала должны убедиться, что установили разные библиотеки для разработки с применением GTK, пакет для разработки программ на языке C, компилятор gcc, программу make, и возможно еще несколько других пакетов для разработки.

### Драйвера и интерфейсы

PDQ позволяет пользователям выбрать принтер на который будет производится печать. Принтер в PDQ определяется как комбинация "драйвера" и "интерфейса". И драйвер и интерфейс являются текстовыми описаниями в файле настройки PDQ.

Интерфейс PDQ описывает то, как данные посылаются на принтер. Наиболее общими интерфейсами, которые поставляются вместе с дистрибутивом PDQ в качестве примера файла printrc, являются:

local-port

  Интерфейс локального порта работает с параллельным или последовательным портом на той машине, на которой запущен PDQ. Используя этот интерфейс PDQ может печать прямо в параллельный порт. Заметьть, что если вы работаете в многопользовательской системе, то это может вызвать неразбериху, и если вы имеете сеть, то интерфейс local-port будет применим только для одной системы. В этих случаях вы можете определить очередь печати lpd без фильтра и без проблем печатать на в эту очередь одинаковым способом со всех систем и пользователей. Интерфейс имеет аргумент -- имя устройства; обычным значением является /dev/lp0.

bsd-lpd

  Интерфейс bsd lpd общается по сети с демоном LPD или с работающим по протоколу LPD сетевым принтером. PDQ поддерживает постановку, отмену заданий и запросы к интерфейсу LPD. Этот интерфейс имеет параметры: имя сервера и название очереди.

appletalk

  Интерфейс appletalk позволяет вам печатать на принтера в сети Appletalk; если у вас есть принтер подключенный к компьютеру Mac, то необходимо использовать этот интерфейс. Этому интерфейсу для работы нужен пакет Netatalk.

Драйвер PDQ описывает как перевести печатаемые данные в формат, который понимает данные принтер. Для принтеров понимающих Postscript, он будет включать преобразования из ascii в Postscript; для не-Postscript принтеров он будет описывать преобразования из Postscript в язык принтер, используя Ghostscript.

Если ни одна из включенных в поставку PDQ спецификаций драйвера не подходит к вашему принтеру, то читайте дальнейшие разделы и пишите свой драйвер.

### Определение принтеров

Для того чтобы определить принтер в PDQ:

- Сначала проверьте, что вы получили правильные определения драйвера и интерфейса в системном или в персональном файле printrc.
- IЕсли вы хотите определить драйвер принтера в файле /etc/printrc (для всех пользователей), то делайте это как администратор.
- Запустите xpdq, и выберите пункт меню Printer->Add printer. Этот мастер настройки проведет вас через выбор нужного драйвера и интерфейса.

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

### Создание определения драйвера PDQ

Здесь я проведу вас по примеру создания объявления драйвера PDQ. До того, как вы начнете этот процесс, загляните в несколько мест, чтобы найти существующие объявления драйверов:

- С PDQ поставляется небольшая коллекция файлов с драйверами.
- В базу данных этого документа включена программа, названная "PDQ-O-Matic", которая сгенерирует спецификацию PDQ из информации в базе данных. При небольших усилиях это может подойти. Это легкий способ если у вас не-Postscript принтер.
- Я написал утилиту, которая называется `ppdtopdq`, и которая берет файл Postscript Printer Definition (определения принтера Postscript) и преобразует его в спецификацию драйвера PDQ. Это правильны способ если у вас принтер понимающий Postscript. Напишите мне, чтобы получить копию.

Вам необходимо заглянуть в несколько мест для того, чтобы найти информацию необходимую для написания вашего драйвера PDQ:

- Синтаксис спецификации драйвера PDQ достаточно богат и полностью документирован в справочной странице printrc(5).
- Дистрибутив PDQ включает несколько файлов-примеров. Посмотрите в файл, описывающий Epson Stylus, который демонстрирует структуру определения для принтера, управляемого Ghostscript.
- База данных Printing HOWTO включает данные примерно о 400 принтерах. Она выдаст информацию о том, какие ключи необходимы для Ghostscript, или какие программы надо запустить для обработки вывода Ghostscript.

Если вы создали свой собственную спецификацию драйвера, или или вы расширили спецификацию из дистрибутива PDQ или сгенерированную вышеупомянутой программой, то пожалуйста поделитесь вашим трудом со всем миром!Пошлите его мне на адрес (`gtaylor+pht@picante.com`), и его смогут найти будущие пользователи PDQ, у которых принтер такого же как у вас типа.

Теперь давайте пройдем сквозь этапы написания спецификации драйвера для принтера, который в базе данных Printing HOWTO отмечен как работающий, но для которого вы не можете найти спецификацию драйвера PDQ. Я буду использовать принтер Canon BJC-210 в качестве примера

Давайте сначала заглянем в информацию об этом принтере. Заметьте, что он поддерживается "великолепно", так что мы можем получить результат, который сравним (или лучше) с результатами, получаемыми пользователями Windows. Важной информацией являются три места в полученной информации:

Драйвер

  Последняя строка в колонке Works?/Language/Driver сообщает нам, что есть драйвер работающий с этим принтером. Более того, это имя является ссылкой на домашнюю страницу с драйвером.

Заметки

  Заметки понятные для людей часто содержат полезную информацию. Для некоторых принтеров существует ссылка "More Info (Больше информаци)", которая обычно ссылается на страницу пользователя, который работает с этим принтером или на странцу драйвера данного принтера.

Список драйверов

  Большинство принтеров имеют список команд драйвера. Это наиболее важная часть.

Спецификация драйвера PDQ имеет две логических функции: взаимодействие с пользователем и обработка задания. Это представляется в файле в трех местах:

Объявление ключей (опций)

  Этот раздел определяет какие ключи могут быть установлены пользователем, и определяют переменные PDQ для дальнейшего использования драйвером.

Языковые фильтры

  Этот раздел описывает процесс преобразования заданий печати из формата в котором они пришли (обычно это Postscript или ASCII) в формат, который понимает принтер (например PCL). Значения ключей доступны в этом разделе, так же как и в фильтре вывода.

Выходной фильтр

  Этот последний фильтр связывает данные принтера независимо от типа входных данных; часто ключи принтера устанавливаются в этом месте.

Давайте продемонстрируем все это для Canon BJC-210:

### Ключи

Список драйверов для данного принтера выглядит следующим образом:

> `

>     Driver: Ghostscript: -sDEVICE=bj200 -r360x360   # (360x360 BW)
>     Driver: Ghostscript: -sDEVICE=bjc600 -r360x360  # (360x360 Color)

> `

Документация в базе данных сообщает нам, что тип драйвера "Ghostscript", который является набором ключей для Ghostscript, без "обычных" ключей, таких как `-q` или файлом, указывающим эти ключи.

BJC-210 поддерживает одну полезную опцию: пользователь должен выбрать в каком режиме будет печатать: в цветном или черно-белом. Давайте объявим это как опцию выбора, названную "MODE":

> `

>     option {
>       var = "MODE"
>       desc = "Print Mode"
>       # default_choice "Color"    # раскомментируйте для установки значения по умолчанию
>       choice "BW" {
>         # Часть value назначает переменной MODE все что вы захотите.
>         # Мы будем назначать текст, который отличается для разных наборов
>         # ключей Ghostscript для каждого из режимов
>         value = "bj200"
>         help = "Fast black printing with the black cartridge."
>         desc = "Black-only"
>       }
>       choice "Color" {
>         value = "bjc600"
>         help = "Full-color printing."
>         desc = "Color"
>       }
>     }

> `

При описанном выше объявлении пользователь будет видеть выбор только из значений Color или BW, в диалоге драйвера принтера при печати через xpdq. В командно-строковой утилите pdq, пользователь может указать ключи `-oBW` или `-oColor`. Значение по умолчанию может быть установлено с помощью xpdq, или объявлено с помощью ключевого слова `default_choice`.

### Обработка типов данных

Обычно PDQ определяет тип входных данных с помощью команды file(1). Для каждого типа, возвращенного командой file, и который вы хотите обрабатывать, вам необходимо определить предложение `language_driver`. Это предложение состоит в основном из скрипта для обработки задания печати, на любом (!) языке скриптов, который вы захотите использовать (языком по умолчанию является язык Bourne shell).

В нашем случае мы хотим печатать Postscript и ASCII на нашем принтере BJC-210. Поэтому нам необходимо два драйвера для типов файлов: один для запуска Ghostscript для заданий в формате Postscript, и один для добавления команд возврата каретки к заданиям в ASCII:

> `

>     # Первый language_driver в этом файле, который соответствует результату
>     # выполнения  file(1) сообщает, что будет использовано
>     language_driver ps {
>       # file(1) возвращает строку "PostScript document text conforming at..."
>       filetype_regx = "postscript"
>       convert_exec = {
>         gs -sDEVICE=$MODE -r360x360 \     # ключи gs из базы данных
>            -q -dNOPAUSE -dBATCH -dSAFER \ # "обычные" ключи Ghostscript
>            -sOutputFile=$OUTPUT $INPUT    # обработка INPUT в файл OUTPUT

>         # Последние две строки часто одинаковы для всех поддерживаемых gs
>         # принтеров. Однако строка gs..., будет разная для каждого из
>         # принтеров.
>       }
>     }

>     # Мы объявили тип text после postscript, потому-что команда "file" часто
>     # описывает файл postscript как текстовый (чем он и является).
>     language_driver text {
>       # Нет filetype_regx; мы ищем соответствие имени драйвера: "text"
>       convert_exec = {#!/usr/bin/perl
>          # Программа на Perl, просто потому-что мы можем писать на нем!
>          my ($in, $out) = ($ENV{'INPUT'}, $ENV{'OUTPUT'});
>          open INPUT, "$in";
>          open OUTPUT, ">$out";
>          while(<INPUT>) {
>             chomp;
>             print OUTPUT, "$_\r\n";
>          }
>       }
>     }

> `

Это все! В то время как другие принтера нуждаются в фильтрации выходных данных (как описано в следующем разделе), вышеприведенное предложение подходит для BJC-210. Мы просто передадим их указанному предложению `driver`:

> `

>     driver canon-bjc210-0.1 {
>       option {
>         var = "MODE"
>         desc = "Print Mode"
>         # default_choice "Color"    # раскомментируйте для установки значения по
>                                                                     # умолчанию
>         choice "BW" {
>           # Часть value назначает переменной MODE все что вы захотите.
>           # Мы будем назначать текст, который отличается для разных наборов
>           # ключей Ghostscript для каждого из режимов
>           value = "bj200"
>           help = "Fast black printing with the black cartridge."
>           desc = "Black-only"
>         }
>         choice "Color" {
>           value = "bjc600"
>           help = "Full-color printing."
>           desc = "Color"
>         }
>       }

>       # Первый language_driver в этом файле, который соответствует результату
>       # выполнения  file(1) сообщает, что будет использовано
>       language_driver ps {
>         # file(1) возвращает строку "PostScript document text conforming at..."
>         filetype_regx = "postscript"
>         convert_exec = {
>           gs -sDEVICE=$MODE -r360x360 \     # gs options from the database
>              -q -dNOPAUSE -dBATCH -dSAFER \ # the "usual" Ghostscript options
>              -sOutputFile=$OUTPUT $INPUT    # process INPUT into file OUTPUT

>           # Последние две строки часто одинаковы для всех поддерживаемых gs
>           # принтеров. Однако строка gs..., будет разная для каждого из
>           # принтеров.
>         }
>       }

>       # Мы объявили тип text после postscript, потому-что команда "file" часто
>       # описывает файл postscript как текстовый (чем он и является).
>       language_driver text {
>         # Нет filetype_regx; мы ищем соответствие имени драйвера: "text"
>         convert_exec = {#!/usr/bin/perl
>            # Программа на Perl, просто потому-что мы можем писать на нем!
>            my ($in, $out) = ($ENV{'INPUT'}, $ENV{'OUTPUT'});
>            open INPUT, "$in";
>            open OUTPUT, ">$out";
>            while(<INPUT>) {
>               chomp;
>               print OUTPUT, "$_\r\n";
>            }
>         }
>       }
>     }

> `

Если вы хотите добавит что-нибудь в начало или конец всех заданий печати, или выполнить какое-нибудь преобразование любых данных любых типов, то воспользуйтесь предложением `filter_exec`. Наш принтер Canon не нуждается в таком предложении, но просто для примера, мы приведем простую иллюстрацию, показывающую как сделать поддержку двухсторонней печати и выбора разрешения на принтерах Laserjet или других моделях, поддерживающих PJL:

> `

>     driver generic-ljet4-with-duplex-0.1 {
>       # Сначала два предложения option для обеспечения выбора пользователя:
>       option {
>         var = "DUPLEX_MODE"
>         desc = "Duplex Mode"
>         default_choice = "SIMPLEX"
>         choice "SIMPLEX" {
>           value = "OFF"
>           desc = "Односторонняя печать"
>         }
>         choice "DUPLEX" {
>           value = "ON"
>           desc = "Двухсторонняя печать"
>         }
>       }

>       option {
>         var = "GS_RES"
>         desc = "Resolution"
>         default_choice = "DPI600"
>         choice "DPI300" {
>           value = "-r300x300"
>           desc = "300 dpi"
>         }
>         choice "DPI600" {
>           value = "-r600x600"
>           desc = "600 dpi"
>         }
>       }

>       # Теперь мы обрабатываем Postscript используя драйвер Ghostscript для ljet4:
>       language_driver ps {
>         filetype_regx = "postscript"
>         convert_exec = {
>            gs -sDEVICE=ljet4 $GS_RES \
>               -q -dNOPAUSE -dBATCH -dSAFER \
>               -sOutputFile=$OUTPUT $INPUT
>         }
>       }

>       # В заключение мы обернем задание в команды PJL:
>       filter_exec {
>         # требуется наличие команды echo с возможностями выдачи кода escape...
>         echo -ne '\33%-12345X' > $OUTPUT

>         echo "@PJL SET DUPLEX=$DUPLEX_MODE"    >> $OUTPUT
>         # Вы можете вставить дополнительные команды @PJL, подобные приведенным выше.
>         # Убедитесь, что вы всегда дополняете (>>) к выходному файлу!

>         cat $INPUT >> $OUTPUT
>         echo -ne '\33%-12345X' >> $OUTPUT
>       }
>     }

> `

## 7.2 Настройка LPD

### Традиционная настройка lpd

Традиционная настройка lpd заканчивается тем, что можно создавать очереди файлов и печатать их. Она не обращает никакого внимания на то понимает ли принтер эти файлы или нет, и скорее всего не позволит производить привлекательный вывод. Тем не менее, это первый шаг к пониманию, так что читайте!

Для добавления очереди печати к lpd, вы должны добавить запись в файл /etc/printcap, и создать новую буферную директорию в каталоге/var/spool/lpd.

Запись в файле /etc/printcap выглядит примерно так:

> `

>     # ЛОКАЛЬНЫЙ djet500
>     lp|dj|deskjet:\
>             :sd=/var/spool/lpd/dj:\
>             :mx#0:\
>             :lp=/dev/lp0:\
>             :sh:

> `

Это определяет принтер называемый lp, dj, или deskjet, его спул размещается в директории /var/spool/lpd/dj, без ограничения максимального размера задания, который печатает на устройство /dev/lp0, и который не имеет страницу с заголовком (с именем человека, который печатает и т.п. информацией) добавленную в начало задания печати.

Теперь прочитайте справочную страницу для printcap.

Вышеприведенный пример выглядит очень простым, но он имеет ловушку -- хотя я посылаю файлы, которые DeskJet 500 может понимать, этот DeskJet будет печатать странные вещи. Например посыл обычного текстового файла Unix приведет к тому, что deskjet будет интерпретировать символы новой строки как символы, и выдаст мне:

> `

>     This is line one.
>                      This is line two.
>                                       This is line three.

> `

Печать файла PostScript на этот принтер выдаст великолепный листинг команд PostScript, напечатанных с этим "лестничным эффектом", а не полезный вывод.

Очевидно требуется что-то сделать, и это является назначением фильтрации. Более наблюдательные из тех кто читал справочную страницу printcap должны были заметить атрибуты принтера if и of. Хорошо, if, или входной фильтр -- это все что нам нужно здесь.

Если мы напишем маленький скрипт, названный filter, который добавляет возврат каретки до символа новой строки, то лестничный эффект будет ликвидирован. Так что мы добавим строку if в нашу, вышеприведенную запись в printcap:

> `

>     lp|dj|deskjet:\
>             :sd=/var/spool/lpd/dj:\
>             :mx#0:\
>             :lp=/dev/lp0:\
>             :if=/var/spool/lpd/dj/filter:\
>             :sh:

> `

Простой скрипт может выглядеть так:

> `

>     #!perl
>     # Предыдущая строка должна содержать полный путь к perl
>     # Скрипт должен быть исполнимым: chmod 755 filter
>     while(<STDIN>){chop $_; print "$_\r\n";};
>     # Вы можете также добавить в конец прогон страницы: print "\f";

> `

Если мы сделаем как приведено выше, мы будем иметь принтер на котором мы сможем печатать обычные текстовые файлы Unix и получать осмысленные результаты. (Конечно мы можем написать этот фильтр четырьмя миллионами лучших способов, но этот более иллюстративный. Вы можете попытаться сделать это более эффективно).

Оставшаяся проблема в том что печать простого текста не является злободневной -- наверняка будет лучше если мы сможем печатать PostScript и другие типы форматированого и графического вывода. Да и это легко сделать. Метод является просто расширением вышеприведенного фильтра для исправления перевода строки. Если вы напишите фильтр, который может воспринимать произвольные типы файлов как ввод и производить вывод для DeskJet для каждого случая, тогда мы безусловно получим "умный" спулер принтера.

Такой фильтр называется magic-фильтр. Не беспокойте себя написанием фильтра, до тех пора пока они не будут печатать странные вещи -- в сети уже существует много хорошо написанных фильтров. APS Filter это лучший среди всех, или ваш дистрибутив Linux может иметь утилиту настройки принтера, которая сделает всю настройку очень простой.

Есть правда ловушка для таких фильтров: некоторые старые версии lpd не запускают фильтр if для удаленных принтеров, а некоторые запускают. Версии lpd используемые в современных дистрибутивах Linux и FreeBSD запускают указанный фильтр; большинство коммерческих юниксов до сих пор поставляются с lpd, которые не запускают фильтр для удаленных принтеров. Смотрите раздел о сетевой печати для более детальной информации.

### Учет ресурсов

Для некоторых систем необходимо хранить информацию о том, кто и как много печатал; этот раздел описывает разные методы выполнения данной работы.

Обычный LPD предоставляет очень небольшую помощь в выполнение учета ресурсов. Вы можете указать имя файла для учета ресурсов используя атрибут af= в printcap, но только передается как параметр вашему фильтру, указанному в if=. Возможно сделать так, что ваш if= фильтр будет писать данные в файл учета ресурсов, и вы будете обрабатывать этот файл позже (традиционный формат в основном полезен для строчных принтеров, и нетривиален для разбора с помощью Perl, так что нет причин сохранять его).

Ghostscript предоставляет оператор PageCount, который вы можете использовать для подсчета страниц в каждом из заданий; обычно вам необходимо добавить несколько строк на postscript в конец задания для того, чтобы дописать запись в файл учета; лучшим примером этого является файл unix-lpr.sh в поставке исходного кода Ghostscript.

Заметьте, что реализация учета ресурсов использованная в unix-lpr пишет в файл из Ghostscript и таким образом несовместима с рекомендованным ключом -dSAFER. Лучшим решением мог бы быть опрос принтера с помощью команды PJL после каждого из заданий, или написать программу на postscript, которая будет выдавать число страниц на стандартный вывод, где данные могут быть захвачены другой программой.

Система буферизации LPRng включает простую реализацию учета ресурсов для HP; я думаю, что она опрашивает принтер используя PJL.

### Большие системы

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

- Каждый принтер должен иметь одну точку контроля, откуда администратор может приостановить, переупорядочить или переназначить задания в очереди. Для реализации этого каждый должен печатать на локальный сервер, который будет выполнять буферизацию заданий и направлять их на соответствующий принтер.
- Используйте LPRng, по крайней мере на серверах; BSD LPD является имеет слишком много недостатков для "нормального" использования.
- Клиентские системы не должны иметь уникальные настройки печати. Для реализации этого используйте расширенный синтаксис printcap в LPRng, так что вы сможете везде использовать один и тот же файл printcap.
- Очереди печати не должны называться по названию производителя или модели; очереди печати лучше именовать лучше по расположению (floor2_nw) или по возможностям (color_transparency). Три года спустя, если сломается принтер, то вы сможете сменить его другой моделью без введения в заблуждение.
- Разработайте страницу web, которая показывает детальную информацию о каждом из принтеров, включая расположение, возможности и т.п. Рассмотрите возможность показа очереди. Сложные сетевые среды неуправляемы без соответствующей документации.
- На машинах с Unix, используйте PDQ для того, чтобы предоставить выбор параметров печати, таких как двухстороннюю печать или размер бумаги, и заставить пользователей запускать все задания Ghostscript под правильным идентификатором пользователя.
- На машинах с Windows и Apple, либо используйте везде поставляемые драйвера (Samba поддерживает механизм автоматической загрузки драйверов) или везде используйте драйвера Postscript. Не смешивайте разные драйвера; примитивные текстовые процессора часто производят разный код при изменении драйвера принтера; пользователи не могут связать изменения в виде с отдельной парой клиент/принтер.
- Если возможно, то покупайте принтер с большими ресурсами для печати в больших объемах. Если возможно по бюджету, то используйте свойство LPRng печати на много принтеров через одну очередь и назначьте "приходящую няню"; принтера являются сложными механическими устройствами, которые будет часто зажимать бумагу или работать без нее в таких конфигурациях.
- Не переживайте, что принтера должны быть подключены к рабочим станциям; сейчас Ethernet "сервера печати" стоят в районе $100. Возможность размещать принтера где есть сеть является большим удобством по сравнению с расположением принтеров около машин; располагайте принтера в разумных, центральных точках.

### Права доступа на файлы

По популярному требованию, я включил ниже список прав доступа на интересующие нас файлы на моей системе. Существует несколько более лучших способов сделать это, в идеале использовать только выполнимые файлы со SGID и не делать все подряд SUID root, но это как пришло в моей системе, и это работает для меня. (Довольно откровенно, если ваш производитель даже не может сделать работающий lpd, то вы в опасной поездке).

> `

>     -r-sr-sr-x   1 root     lp    /usr/bin/lpr*
>     -r-sr-sr-x   1 root     lp    /usr/bin/lprm*
>     -rwxr--r--   1 root     root  /usr/sbin/lpd*
>     -r-xr-sr-x   1 root     lp    /usr/sbin/lpc*
>     drwxrwxr-x   4 root     lp    /var/spool/lpd/
>     drwxr-xr-x   2 root     lp    /var/spool/lpd/lp/

> `

В настоящее время lpd должен быть запущен под правами администратора, так что он может быть связан с сервисным портом lp с низким номером. Он должен вероятно быть с UID lp.lp или каким-то после связывания, но я не знаю с каким.

PDQ использует отличную от других схему, не ориентированную на демонов, и поэтому у него другие программы. Только несколько программ имеют установленный бит SUID и владельца администратора, эта программы являются интерфейсом к lpd и называются `lpd_cancel`, `lpd_print` и `lpd_status`; эти программы имеют SUID, потому-что сервера печати Unix требуют отправки запросов с привилегированного порта. Если вам необходимо применять интерфейс bsd-lpd из поставки PDQ только для сетевых принтеров печати таких как адаптеры HP JetDirect или Lexmark MarkNet), то вам не нужно устанавливать бит suid на эти программы.

Next Previous Contents