Жанр: Учеба

Приемы профессиональной работы в Unix

сторінка №18


Такая последовательность иллюстрирует проверку на ошибки внутри
программы. Сначала включается подсчет времени для текущего файла проекта,
а затем он включается опять. Timelog распознает это и сообщает,
что вы должны отключить подсчет перед тем, как снова включить его.

3. s,junk

Эта последовательность также иллюстрирует проверку ошибок. Пытаемся
выбрать новое имя файла проекта. Имя файла junk (которого вы не
имеете). Timelog проверяет, существует ли файл регистрации времени с
именем junk. Если нет, выводится сообщение о том, что вы должны выбрать
правильное имя файла проекта.

ПОЯСНЕНИЯ

В этом командном файле много текста, но замысел не очень сложен.
Строка 4 инициализирует переменную PROJ нулевым значением. PROJ -
это переменная, которая содержит имя проекта, отображаемое в меню. В
начале работы мы должны быть уверены, что эта переменная установлена в
нуль.
Строки 6-104 - это огромный бесконечный цикл while, который выполняет
работу всей программы. Поскольку это бесконечный цикл, мы можем
выйти из него либо оператором break, (вводя обычные символы прерывания),
либо с помощью команды выхода.
В строке 8 позиционным параметрам присваивается результат команды
date. Поступая таким образом, мы можем затем легко обращаться к каждому
полю без выделения его командой cut - shell выполняет за нас синтаксический
разбор полей. Мы можем ссылаться на поля даты в виде $1,
$2 и т.д.
Строки 9-23 выводят на экран главное меню. Верхняя строка обращается
к данным из команды date. $1, $2 и $3 представляют собой день недели,
месяц и число. $4 - это время. Перед тем как команда echo выводит
текстовые строки, эти переменные раскрываются таким образом, что
они появляются в меню. Если переменная PROJ равна нулю, то ничего не
печатается в качестве имени текущего проекта. Символы \c в конце огромного
оператора echo устанавливают курсор после приглашения в этой
же строке, так что мы готовы принимать вводимые пользователем символы.
После печати меню в переменную RSP читается ответ в строке 25.
Затем наступает черед огромного оператора case (строки 27-103), который
содержит ветку для каждой команды.
В строке 28 проверяется, не был ли ответ всего лишь возвратом каретки,
указывающим, что пользователь хочет выйти. Если был, то цикл
while завершается посредством команды break и программа заканчивает
работу.
Иногда возврат каретки - более желательный метод выхода, чем команда
exit интерпретатора shell. В конечном итоге эта команда shell
приводит к выполнению программ exit и _exit Си -интерфейса. Выполнение
вызова exit в Си иногда приводит к неожиданным побочным эффектам, в то
время как нормальное выполнение текста программы до конца не дает таких
же результатов. Однажды мы столкнулись с такой проблемой при
использовании ESC -последовательностей для изменения цвета на цветном
мониторе. Когда программа завершалась нормально, цвет не переустанавливался.
Однако когда был сделан системный вызов exit, печатались некоторые
ESC-последовательности, что переустанавливало отдельные части
экрана. Очень странно!
Строки 29-38 управляют функцией выбора проекта. Имя проекта запрашивается
и читается в переменную PROJ2. PROJ2 использована для временного
хранения этого значения. Если был введен возврат каретки, оператор
continue приводит к следующей итерации внешнего цикла while. Это
позволяет пользователю прекратить выполнение этой функции при ошибочном
вводе, оставаясь все же в timelog. Если ввод был непустым, файл
проекта проверяется на существование и на наличие в нем данных. Если
файл не существует, пользователя просят указать верное имя проекта.
Если имя файла правильное, то переменной PROJ присваивается значение
PROJ2. Только после того, как командный файл с уверенностью знает, что
имя, введенное пользователем, допустимо, оно назначается в качестве
текущего имени проекта. Это предохраняет от потери выбора текущего
проекта из-за ошибки пользователя. Теперь PROJ выводится в меню на экран.

Команда создания обрабатывается строками 39-50. Снова запрашивается
имя и проверяется, не равно ли оно нулю. Если имя было введено,
то проверяется, существует ли уже такой файл. Мы не хотим снова создавать
и затирать уже имеющийся файл. Файл создается в строке 50. В этот
файл выводятся отметка о времени его инициализации и начальное сообщение
о том, что подсчет времени отключен.

Опция вывода списка выполняется в строках 51-53. Выводится заголовок,
а затем команда ls используется для генерации списка. Если нет
файлов нужного нам типа, то команда ls возвращает статус, отличный от
нуля, тем самым включается оператор ||. В сущности этот фокус shell
дает нам встроенный оператор if-then, который может использовать результаты
предыдущей команды. Если выполнение команды ls неудачно (т.е.
не найдены подходящие файлы), это сообщение об ошибке отбрасывается
(не выводится) и выполняется оператор echo. Команда echo сообщает, что
нет файлов, чтобы вы знали об этом.
Всякий выход команды ls пропускается через команду sed для отбрасывания
расширения имени файла .time. Для сохранения места и для
удобства пользователя мы хотим только посмотреть и напечатать имена
проектов, а не имена файлов. Однако, мы хотим хранить имена файлов в
специальном внутреннем формате так, чтобы мы могли проще обрабатывать
их и поддерживать уникальные имена.
Команда просмотра выполняется в строках 54-60. Текущий файл проекта
проверяется на то, было ли выбрано имя. Если нет, главное меню
выводится снова. В противном случае печатается строка из черточек, выводится
командой more файл проекта и печатается еще одна строка черточек
для обрамления выведенной информации. Вы можете удивиться, почему
первым символом оператора echo является двоеточие (:). Это некоторый
казус, поскольку, если вы попытаетесь отобразить символ черточки (-) в
качестве первого символа, то оператор echo "подумает", что это пустая
опция и не выведет ее на экран. Вы просто должны поставить в первой
позиции какой-то непустой символ, отличный от черточки.
Включение подсчета времени выполняется в строках 61-70. Текущее
имя проекта проверяется на то, было ли оно выбрано. Если да, то проверяется,
был ли отключен файл проекта. Мы выполняем это, используя команду
tail для выделения последней строки файла, затем передаем по
конвейеру эту строку команде cut, где мы изменяем символ-разделитель
на символ : и отрезаем первое поле. Если в этом поле находятся символы
OFF, все в порядке. После этого строка 69 выводит на экран сообщение
для пользователя, а строка 70 вставляет в файл проекта строку ON, за
которой следует текущая дата. Тем самым файл отмечается как включенный.
Подсчет времени начался. Если эта операция уже была включена, мы
сообщаем об этом пользователю и выходим из данной операции меню.
Строки 71-80 обрабатывают отключение подсчета времени. Здесь почти
все идентично тексту программы, который включает эту операцию,
только если там было слово "on", то здесь слово "off".
Строки 81-101 обрабатывают подчиненное меню выдачи отчетов и статистики.
Как видите, экранное меню спланировано таким же образом: цикл
while, печать меню, чтение ответа, выполнение оператора case в зависимости
от выбранной команды и т.д. Команда r подобна главному меню,
только сокращена для того, чтобы поместиться внутри оператора case. Вы
также можете заметить, что в строках 96-99 выполняется не очень много
обработки. Это то место, где вы должны выполнить некоторую работу.
Строка 102 выполняет обработку ошибок при любом неверном вводе.
Печатается сообщение об ошибке, оператор case выходит на следующую
итерацию цикла while, и все начинается сначала.

МОДИФИКАЦИИ

Основной возможностью для модификации является добавление фактической
обработки информации о времени. Один из подходов к этому - запросить
почасовой тариф времени в момент создания файла проекта (если
считать, что вы работаете на таких основаниях). Этот тариф может храниться
первым пунктом в файле проекта. Следующие две строки могут быть
отведены для "счета по текущему сеансу" и "общего счета" соответственно.
Когда подсчет времени работы над проектом отключается, можно проанализировать
текущее системное время и начальное время подсчета и затем
пересчитать в минуты (для упрощения арифметики) с использованием
команды expr (или, возможно, awk). Затем это значение можно умножить
на хранимый в файле тариф времени, а результат сохранить в записи о
текущем сеансе работы и ДОБАВИТЬ к совокупной общей записи.

---------------------------------------------------------------------------

ИМЯ: today
---------------------------------------------------------------------------

today Печать календаря с подсвеченной сегодняшней датой

НАЗНАЧЕНИЕ

Модифицирует вывод утилиты cal для печати сегодняшней даты ин-
версным цветом.


ФОРМАТ ВЫЗОВА

today

ПРИМЕР ВЫЗОВА

today Печатает календарь на этот месяц с подсвеченной
сегодняшней датой

ТЕКСТ ПРОГРАММЫ today

1 :
2 # @(#) today v1.0 Calendar with today highlighted
Author: Russ Sage
2а Календарь с подсветкой сегодняшнего дня

4 SYSV=n

6 set `date`

8 if [ "$SYSV" = "y" ]
9 then RVR=`tput smso`
10 BLNK=`tput blink`
11 NORM=`tput rmso`
12 cal ${2} ${6} | sed "s/${3}/${RVR}${BLNK}${3}${NORM}
/g" -e "s/^/ /"
13 else RVR="^[[7m" # termcap so
14 NORM="^[[0m" # termcap se
15 cal ${2} ${6} | sed -e "s/ ${3}/ ${RVR}${3}${NORM}
/" -e "s/^/ /"
16 fi

ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ

RVR Управляющий символ инверсного отображения для
вашего терминала
BLNK Управляющий символ мерцания для вашего терминала,
если таковой имеется
NORM Управляющий символ для возврата терминала в
обычный режим

ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖЕН today?

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

ЧТО ДЕЛАЕТ today?

Today - это постпроцессор для команды cal, который делает ее результат
более информативным и графически наглядным. Выполнение модификации
команды cal зависит от того, в какой системе вы работаете. Если
вы в системе UNIX System V (версия 2 или старше), то у вас есть утилита
terminfo. Terminfo является заменой для файла termcap и поставляется
с несколькими утилитами, которые возвращают значения с информацией
о ПРИЕМЫ ПРОФЕССИОНАЛЬНОЙ РАБОТЫ В UNIX
нальных характеристик. Если ваш компьютер работает не с системой
System V, то вам необходимо немного поисследовать тип ваших конкретных
терминалов и внести полученные значения в вашу программу.
Вся история с утилитами termcap и terminfo иллюстрирует эволюцию
работы в среде UNIX. UNIX с самых первых дней стремился быть независимым
от типов устройств. Первым шагом явилось использование файлов устройств
и драйверов. Следующим шагом был файл termcap, который предоставил
единообразный способ получения информации о терминалах.

Последним этапом является утилита terminfo, предоставляющая эту информацию
таким способом, который лучше обеспечивает функциональный доступ
из программ.
Поскольку в пределах командного файла не так легко определить, с
какой системой работает ваш компьютер, использована переменная SYSV.
Эту переменную можно изменить при помощи редактора, поэтому today может
работать в разных системах. Способами выяснения системы могли бы
служить программа uname, существование определенных shell-программ в
каталоге /bin или какой-нибудь системный файл, содержащий номер
версии. По умолчанию переменная SYSV установлена так, чтобы утилита
today работала НЕ в системе System V. С этим связано существование
фрагмента программы, который нужно изменять вручную.
Как вы можете самостоятельно получить информацию о терминале?
Каждый терминал имеет свои специфические особенности. Все терминалы
характеризуются в основном файлом описания терминала termcap. В этом
файле каждая характеристика дается под своим именем вместе с аппаратным
кодом этой функции. Таким образом, мы можем, например, редактором
vi заглянуть в termcap и увидеть, как управлять терминалом, на котором
мы работаем. Файл termcap сильно зашифрован и загадочен. По данному
вопросу не очень много документации, что порождает множество экспериментов
и ошибок.
Переменными, которые нас интересуют, являются "so" для выделения
информации (инверсный режим) и "se" для завершения выделения (обычный
режим), а также режим мерцания, если он есть у вашего терминала.
Termcap, похоже, не содержит информацию о том, как включить режим мерцания,
поэтому вам, вероятно, нужно будет для этого посмотреть документацию
на терминал. В системе System V (версия 2) команда tput возвращает
соответствующее значение.
По умолчанию в today выполнены установки для ANSI терминала, являющегося
консольным в системе XENIX. Эти коды были вручную извлечены
из файла /etc/termcap и вставлены в текст программы. Если ваши коды
отличаются, вы должны выяснить их. Обратите внимание, что в файле
/etc/termcap символ ESCAPE представлен как \E. Это не годится для
today, и вы должны изменить такое представление на настоящий ESCAPE.
Поскольку ESCAPE является символом выхода из режима ввода в редакторе
vi, вы должны использовать команду control-V в этом редакторе для ввода
управляющих символов. Последовательность control-V вызывает печать
символа ^, а ESCAPE - печать символа [. Таким образом, реальная команда
входа в инверсный режим в редакторе vi представлена последовательностью
^[[7m. Эта команда включает символы ^[ в качестве ESCAPE и затем
обычные символы [7m для изменения режима.
Теперь, когда характеристики терминала учтены, цель утилиты today
- выделить текущий день календаря в инверсном виде, а все остальное
оставить в обычном виде. Это делается путем передачи по конвейеру выхода
команды cal команде sed. Утилита sed находит число в выходных
данных и подставляет специальную графическую ESC-последовательность.
Поскольку ваш терминал использует специальные символы для изменения
режима, вы не увидите их выдачи на экран.
Данная программа не имеет опций или какого-то особого входа. Она
распечатывает календарь с отмеченным сегодняшним днем.

ПОЯСНЕНИЯ

В строке 4 выполняется инициализация переменной SYSV значением
"n". Это заставляет программу переходить к особой области, в которой
жестко закодированы управляющие коды терминала, определенные вручную.
Если вы работаете с последними версиями системы System V, то вам нужно,
чтобы эта переменная имела значение "y".
В строке 6 позиционным параметрам присваивается результат команды
date. Мы обратимся к этим значениям позже.
Строки 8-16 - это остальная часть программы. Они представляют собой
один оператор if-then-else. Строки 9-12 поддерживают принятый в
System V метод tput для получения характеристик терминала, а строки
13-15 управляют ручным способом их получения.
В обоих случаях переменным shell присваиваются ESC-последовательности.
Эти значения используются позже. В обоих случаях выполняется
вызов команды cal с использованием значений месяца и года, полученных
от команды date. Этот образ календаря пропускается по конвейеру через
утилиту sed, которая ищет указанный день "сегодня", также полученный
от команды date. Когда этот день найден, sed заменяет цифры дня на
последовательность включения инверсного режима, последовательность
включения режима мерцания, если он есть, и символы дня, а затем последовательность
возврата в обычный режим работы терминала. Последняя команда
sed заполняет пробелами начало строки для размещения ее в центре
экрана.


УПРАВЛЕНИЕ ДЕЛОПРОИЗВОДСТВОМ

Много рабочего времени тратится на запоминание важной информации,
такой как деловые встречи, адреса, номера телефонов, расписания, учетные
сведения о проектах и так далее. Большинство из такой информации
может быть сохранено в системе UNIX в виде простых структурированных
текстовых файлов, которыми можно манипулировать с помощью соответствующих
средств. Автоматизация этой области может освободить много времени
для выполнения "настоящей" работы.
Хотя мощные коммерческие программы для сохранения такой информации
имеются в среде MS-DOS, эти программы не имеют широкого распространения
в UNIX. Часто у вас нет необходимости в отдельной большой
программе для выполнения таких работ в UNIX. UNIX обеспечивает хороший
компромисс между легкими в применении, но не гибкими коммерческими
программами и программированием на мощных, но непростых в использовании
традиционных языках программирования. Возможности языка shell плюс
богатый ассортимент встроенных команд UNIX дают мощный, гибкий и СРАВНИТЕЛЬНО
простой в использовании компромисс. В данном разделе мы
представляем широкий набор средств управления личной информацией, которые
вы можете приспособить для своих нужд.
Для шутки начнем с программы по имени jargon - генератора технических
терминов, конструирующего замысловатые фразы. С его помощью
можно удивлять людей тем, как много вы знаете, или начать прибыльную
вторую карьеру в качестве составителя рекламы. Комбинирование слов порождает
сотни фраз.
Затем мы рассмотрим программу phone. Phone - это командный файл,
управляемый с помощью меню, который поддерживает базу телефонных номеров
и сопутствующей информации. Она сводит воедино разнообразные
аспекты сопровождения базы данных и обслуживания запросов к ней.
Последнее инструментальное средство называется office. Это управляемая
при помощи меню утилита, которая дает одноклавишный доступ ко
всем функциям делопроизводства. Сюда относятся почта, новости, календарь,
номера телефонов и автоматические напоминания.

---------------------------------------------------------------------------

ИМЯ: jargon
---------------------------------------------------------------------------

НАЗНАЧЕНИЕ

Компьютеризованная версия старого настольного генератора техни-
ческих терминов.

ФОРМАТ ВЫЗОВА

jargon

ПРИМЕР ВЫЗОВА

jargon Если ввести 125 в ответ на запрос, то на выходе
125 получится фраза Total Monitored Concept

ТЕКСТ ПРОГРАММЫ jargon

1 :
2 # @(#) jargon v1.0 Technical jargon generator
Author: Russ Sage
2а Генератор технического жаргона

4 echo "\n\t\tThe Jargon Generator"
5 while :
6 do
7 echo "\nEnter a 3 digit number (000-999), ?
, or : \c"
8 read NUM

10 case $NUM in
11 "") exit;;
12 \?) cat " /dev/
null ||
27 { echo "\nNot a valid number, try again
"; continue; };;
28 *) echo "\nInvalid input, try again"
29 continue;;
30 esac

32 N1=`echo $NUM|cut -c1`
33 N2=`echo $NUM|cut -c2`
34 N3=`echo $NUM|cut -c3`
35 SEN=""

37 case $N1 in
38 0) SEN="${SEN}Integrated ";;
39 1) SEN="${SEN}Total ";;
40 2) SEN="${SEN}Systematized ";;
41 3) SEN="${SEN}Parallel ";;
42 4) SEN="${SEN}Functional ";;
43 5) SEN="${SEN}Responsive ";;
44 6) SEN="${SEN}Optional ";;
45 7) SEN="${SEN}Synchronized ";;
46 8) SEN="${SEN}Compatible ";;
47 9) SEN="${SEN}Balanced ";;
48 esac

50 case $N2 in
51 0) SEN="${SEN}Management ";;
52 1) SEN="${SEN}Organizational ";;
53 2) SEN="${SEN}Monitored ";;
54 3) SEN="${SEN}Reciprocal ";;
55 4) SEN="${SEN}Digital ";;
56 5) SEN="${SEN}Logistical ";;
57 6) SEN="${SEN}Transitional ";;
58 7) SEN="${SEN}Incremental ";;
59 8) SEN="${SEN}Operational ";;
60 9) SEN="${SEN}Third-Generation ";;
61 esac

63 case $N3 in
64 0) SEN="${SEN}Options";;
65 1) SEN="${SEN}Flexibility";;
66 2) SEN="${SEN}Capability";;
67 3) SEN="${SEN}Mobility";;
68 4) SEN="${SEN}Programming";;
69 5) SEN="${SEN}Concept";;
70 6) SEN="${SEN}Time-Phase";;
71 7) SEN="${SEN}Projection";;
72 8) SEN="${SEN}Hardware";;
73 9) SEN="${SEN}Contingency";;
74 esac

76 echo "\n\"$SEN\""
77 done

ПЕРЕМЕННЫЕ СРЕДЫ ВЫПОЛНЕНИЯ

N1 Первая цифра числа
N2 Вторая цифра числа
N3 Третья цифра числа
NUM Число, введенное пользователем с клавиатуры
SEN Предложение, полученное из найденных слов

ОПИСАНИЕ

ЗАЧЕМ НАМ НУЖЕН jargon?

В нашем скоростном, заполненном техникой мире на нас оказывается
большое давление с целью получения каких-то результатов. К сожалению,
быстрота современной техники относится к выполнению программ, а не к
их созданию. Когда мы сделали всего лишь третью часть программы, а уже
пора ее предъявлять на рынок - как мы можем создать впечатление, что
наш продукт делает больше, чем на самом деле? Необходимо немного
пустить пыль в глаза заказчику. Пускание пыли состоит из фраз, которые
выглядят и звучат впечатляюще. При строгой проверке мы можем увидеть,
что фраза составлена из настоящих английских слов, значение которых
можно посмотреть в словаре. Эта фраза в целом совершенно бессмысленна,
но если нам повезет, то читатель этого не заметит!
Одним из простых способов получения таких вещей является наличие
таблицы взаимозаменяемых слов, которые можно использовать для составления
предложений. Если у вас система BSD, то вы можете запустить
jargon вместе с программой fortune, которая имитирует случайные подарки
судьбы. Мудрость веков может принадлежать вам!


ЧТО ДЕЛАЕТ jargon?

Jargon - это инструмент для генерации фраз, состоящих из технических
терминов. Строится фраза, которая является комбинацией трех
слов. Первые два слова являются прилагательными, используемыми для
описания третьего слова, имени существительного. Каждое слово выбирается
из столбца, содержащего десять возможных слов. Именно это придает
программе jargon ее творческие способности. Она может объединять слово
из одного столбца с любым словом из другого столбца для построения
многих полезных фраз. Если вы хотите увидеть всю таблицу слов, введите
символ ?. Вот пример таблицы:

---------------------------------------------------------------------------

|
| The Jargon Generator
|
| Enter a 3 digit number (000-999), ?, or : ?
|
| 0. Integrated 0. Management 0. Options
| 1. Total 1. Organizational 1. Flexibility
| 2. Systematized 2. Monitored 2. Capability
| 3. Parallel 3. Reciprocal 3. Mobility
| 4. Functional 4. Digital 4. Programming
| 5. Responsive 5. Logistical 5. Concept
| 6. Optional 6. Transitional 6. Time-Phase
| 7. Synchronized 7. Incremental 7. Projection
| 8. Compatible 8. Operational 8. Hardware
| 9. Balanced 9. Third-Generation 9. Contingency
|

Имеется три возможных варианта ввода. Вы можете ввести трехзначное
число, знак вопроса для печати таблицы или возврат каретки для выхода
из программы. Проверяется, является ли строка из трех цифр допустимым
числом. Если все в порядке, то введенное число разбивается на
три составляющие его цифры. Каждая цифра используется как ключ поиска
в массиве из десяти слов для получения куска предложения. Затем все
слова объединяются для формирования жаргонной фразы. После этого вам
выдается запрос на дальнейший ввод.
Если вы ввели знак вопроса, печатается таблица слов, как показано
в предыдущем примере, и вам снова выдается запрос. Если был введен
только возврат каретки, то цикл, выдававший запросы, завершается и заканчивается
выполнение программы.
Внутри самой программы выполняется только проверка на ошибки.
Программа jargon организована аналогично программе, управляемой с помощью
меню, однако никакого меню нет. Это просто цикл, который выполняется
до тех пор, пока не будет нажат возврат каретки.

ПРИМЕРЫ

1. $ jargon

898


Открывается секрет, что у меня персональный компьютер 898, то
есть Compatible Third-Generation Hardware (совместимая аппаратура
третьего поколения).

2. $ jargon

187


Оказывается это Total Operational Projection (всеобъемлющий разрабатываемый
проект).

ПОЯСНЕНИЯ

Строка 4 печатает заголовок при начальном запуске программы.
Отображается возврат каретки, две табуляции и сообщение.
Строки 5-77 представляют собой один большой бесконечный цикл
while. В нем имеется всего одна точка выхода, находящаяся внутри оператора
case. Строка 7 выводит приглашение, а строка 8 читает вводимый
ответ в переменную NUM.
Строки 10-30 являются оператором case, который проверяет информацию,
введенную с клавиатуры. Если был введен только возврат каретки,
строка 11 рассматривает это как нулевой ввод. В этом случае выполняется
выход из программы. Это и есть нормальная точка выхода.
Ввод вопросительного знака соответствует строке 12. Обратите внимание,
что знак вопроса экранирова

Список сторінок

Поділитися у соцмережах

☏ Замовлення реклами: +3805044-68-872

© Асоціація електронних бібліотек України

☝ Усі матеріали сайту (зокрема статті, зображення, рекламні оголошення тощо) призначені лише для попереднього ознайомлення. Усі права на публікації, представлені на сайті, належать їхнім законним власникам. Просимо Вас не зберігати копії інформації.