feat: add Kyocera rastertokpsl CUPS wrapper
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2026 Contributors to cups-kyocera-rastertokpsl-fix
|
||||
|
||||
SPDX-License-Identifier: CC0-1.0
|
||||
-->
|
||||
|
||||
# CUPS wrapper для Kyocera `rastertokpsl`
|
||||
|
||||
Обёртка для CUPS-фильтра `rastertokpsl`, предназначенная для устранения падений оригинального Kyocera-фильтра при печати заданий с длинными или не-ASCII названиями.
|
||||
|
||||
## Проблема
|
||||
|
||||
Некоторые версии Kyocera `rastertokpsl` используют фиксированный буфер для обработки названия задания. При передаче длинной строки или строки с кириллицей это может приводить к переполнению буфера и аварийному завершению фильтра:
|
||||
|
||||
```text
|
||||
*** buffer overflow detected ***: terminated
|
||||
```
|
||||
|
||||
В журналах CUPS это может выглядеть примерно так:
|
||||
|
||||
```text
|
||||
PID 30752 (/usr/lib/cups/filter/rastertokpsl) crashed on signal 6
|
||||
```
|
||||
|
||||
В результате задание не печатается, а очередь принтера может перейти в состояние `stopped`.
|
||||
|
||||
## Решение
|
||||
|
||||
Wrapper перехватывает аргументы CUPS перед запуском оригинального `rastertokpsl`.
|
||||
|
||||
Перед передачей названия задания оригинальному фильтру wrapper:
|
||||
|
||||
- преобразует UTF-8 в ASCII;
|
||||
- удаляет неподдерживаемые символы;
|
||||
- ограничивает длину строки;
|
||||
- использует `print-job`, если после обработки строка оказалась пустой.
|
||||
|
||||
Оригинальный бинарник сохраняется под именем:
|
||||
|
||||
```text
|
||||
/usr/lib/cups/filter/rastertokpsl.real
|
||||
```
|
||||
|
||||
Wrapper устанавливается вместо него:
|
||||
|
||||
```text
|
||||
/usr/lib/cups/filter/rastertokpsl
|
||||
```
|
||||
|
||||
## Установка
|
||||
|
||||
Сначала сохраните оригинальный фильтр:
|
||||
|
||||
```bash
|
||||
sudo cp /usr/lib/cups/filter/rastertokpsl \
|
||||
/usr/lib/cups/filter/rastertokpsl.real
|
||||
```
|
||||
|
||||
Создайте файл wrapper:
|
||||
|
||||
```bash
|
||||
sudo nano /usr/lib/cups/filter/rastertokpsl
|
||||
```
|
||||
|
||||
Содержимое:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
REAL="/usr/lib/cups/filter/rastertokpsl.real"
|
||||
|
||||
# Kyocera rastertokpsl uses the following arguments:
|
||||
# $1 printer
|
||||
# $2 job-id
|
||||
# $3 title
|
||||
# $4 copies
|
||||
# $5 options
|
||||
|
||||
if [ "$#" -ne 5 ]; then
|
||||
echo "ERROR: rastertokpsl wrapper: expected 5 arguments, got $#" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printer="$1"
|
||||
job_id="$2"
|
||||
title="$3"
|
||||
copies="$4"
|
||||
options="$5"
|
||||
|
||||
# Convert the title to ASCII, remove unsupported characters,
|
||||
# and limit its length to 20 characters.
|
||||
safe_title="$(
|
||||
printf '%s' "$title" |
|
||||
iconv -f UTF-8 -t ASCII//TRANSLIT 2>/dev/null |
|
||||
LC_ALL=C tr -cd 'A-Za-z0-9' |
|
||||
tail -c 20
|
||||
)"
|
||||
|
||||
[ -n "$safe_title" ] || safe_title="print-job"
|
||||
|
||||
# Pass the raster data through stdin.
|
||||
exec "$REAL" \
|
||||
"$printer" \
|
||||
"$job_id" \
|
||||
"$safe_title" \
|
||||
"$copies" \
|
||||
"$options"
|
||||
```
|
||||
|
||||
Назначьте права:
|
||||
|
||||
```bash
|
||||
sudo chown root:root /usr/lib/cups/filter/rastertokpsl
|
||||
sudo chmod 755 /usr/lib/cups/filter/rastertokpsl
|
||||
sudo chmod 755 /usr/lib/cups/filter/rastertokpsl.real
|
||||
```
|
||||
|
||||
Перезапустите CUPS:
|
||||
|
||||
```bash
|
||||
sudo systemctl restart cups
|
||||
```
|
||||
|
||||
## Проверка
|
||||
|
||||
Убедитесь, что оригинальный файл является исполняемым бинарником:
|
||||
|
||||
```bash
|
||||
file /usr/lib/cups/filter/rastertokpsl.real
|
||||
```
|
||||
|
||||
Ожидается вывод с `ELF ... executable`.
|
||||
|
||||
Проверьте печать обычного задания:
|
||||
|
||||
```bash
|
||||
lp -d PRINTER /tmp/test.pdf
|
||||
```
|
||||
|
||||
Затем проверьте длинное название задания:
|
||||
|
||||
```bash
|
||||
lp -d PRINTER \
|
||||
-t "Очень длинное кириллическое название задания для проверки" \
|
||||
/tmp/test.pdf
|
||||
```
|
||||
|
||||
Посмотреть состояние очереди:
|
||||
|
||||
```bash
|
||||
lpstat -p
|
||||
lpstat -o
|
||||
```
|
||||
|
||||
При необходимости включить подробное логирование CUPS:
|
||||
|
||||
```bash
|
||||
sudo cupsctl --debug-logging
|
||||
sudo tail -F /var/log/cups/error_log
|
||||
```
|
||||
|
||||
После завершения диагностики:
|
||||
|
||||
```bash
|
||||
sudo cupsctl --no-debug-logging
|
||||
```
|
||||
|
||||
## Восстановление оригинального фильтра
|
||||
|
||||
Чтобы удалить wrapper и вернуть оригинальный `rastertokpsl`:
|
||||
|
||||
```bash
|
||||
sudo mv /usr/lib/cups/filter/rastertokpsl.real \
|
||||
/usr/lib/cups/filter/rastertokpsl
|
||||
|
||||
sudo systemctl restart cups
|
||||
```
|
||||
|
||||
## Ограничения
|
||||
|
||||
Wrapper рассчитан на конкретный вариант интерфейса Kyocera `rastertokpsl`, использующий пять аргументов:
|
||||
|
||||
```text
|
||||
printer job-id title copies options
|
||||
```
|
||||
|
||||
Размер `20` символов выбран как консервативное ограничение для проблемных версий фильтра. Точный размер внутреннего буфера конкретной версии `rastertokpsl` зависит от драйвера и не определяется самим CUPS.
|
||||
|
||||
Перед установкой рекомендуется сохранить исходный бинарник и проверить версию драйвера.
|
||||
|
||||
## Структура
|
||||
|
||||
Пример структуры репозитория:
|
||||
|
||||
```text
|
||||
cups-kyocera-rastertokpsl-fix/
|
||||
├── README.md
|
||||
└── rastertokpsl
|
||||
```
|
||||
|
||||
Файл `rastertokpsl` из репозитория устанавливается в:
|
||||
|
||||
```text
|
||||
/usr/lib/cups/filter/rastertokpsl
|
||||
```
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
REAL="/usr/lib/cups/filter/rastertokpsl.real"
|
||||
|
||||
# Kyocera rastertokpsl uses the following arguments:
|
||||
# $1 printer
|
||||
# $2 job-id
|
||||
# $3 title
|
||||
# $4 copies
|
||||
# $5 options
|
||||
|
||||
if [ "$#" -ne 5 ]; then
|
||||
echo "ERROR: rastertokpsl wrapper: expected 5 arguments, got $#" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printer="$1"
|
||||
job_id="$2"
|
||||
title="$3"
|
||||
copies="$4"
|
||||
options="$5"
|
||||
|
||||
# Convert the title to ASCII, remove unsupported characters,
|
||||
# and keep only the last 20 alphanumeric characters.
|
||||
safe_title="$(
|
||||
printf '%s' "$title" |
|
||||
iconv -f UTF-8 -t ASCII//TRANSLIT 2>/dev/null |
|
||||
LC_ALL=C tr -cd 'A-Za-z0-9' |
|
||||
tail -c 20
|
||||
)"
|
||||
|
||||
[ -n "$safe_title" ] || safe_title="print-job"
|
||||
|
||||
# Pass the raster data through stdin.
|
||||
exec "$REAL" \
|
||||
"$printer" \
|
||||
"$job_id" \
|
||||
"$safe_title" \
|
||||
"$copies" \
|
||||
"$options"
|
||||
Reference in New Issue
Block a user