chat - это язык сценариев общего назначения, применяемый для управления модемом, выполнения звонка и регистрации на удаленном сервере, chat не столь функционален, как dip, но достаточно широко используется. Структура сценария chat - «ожидание/передача» - является общей для большинства подобных языков.
chat-еценарий состоит из пар ожидание/передача. Пара состоит из двух значений, разделенных пробельными символами. Первое значение представляет строку, которая ожидается от удаленной системы, второе - строку, которую следует передать в ответ. Специальный случай, когда нет необходимости получать строку от удаленной системы, обозначается парой двойных ("") или одинарных (" ) кавычек. В качестве примера рассмотрим простейший сценарий:
"" \r name > jane word> TOga!toGA
Сценарий не ожидает получения каких-либо строк (""), пока удаленной системе не будет передан символ возврата каретки (\г). Затем сценарий ожидает получения от удаленной системы строки name>, которая является частью системного приглашения Username>. В ответ на приглашение сценарий передает регистрационное имя пользователя, jane. Наконец, сценарий ожидает получения части приглашения Password> и отвечает паролем TOga! toGA. Сценарий настолько простой, что его можно создать прямо в командной строке программы chat:
% chat -v -t30 "" \r name> jane word> TOgaltoGA
Приведенная команда запускает chat в режиме подробной диагностики, устанавливает длительность ожидания строки в 30 секунд, а затем выполняет простой сценарий регистрации в удаленной системе. Синтаксис команды chat:
chat [ключи] [сценарий]
Ключи команды chat:
-е - Отображать на экране вывод модема в поток stderr. Идентичный результат можно получить при помощи ключевого слова ECHO в chat-сценарии.
-Е - Разрешает использование переменных среды в тексте сценария.
-s - Предписывает направлять все записи журнала и сообщения об ошибках в поток stderr.
-S - Запрещает направлять сообщения журнала и сообщения об ошибках службе SYSLOG.
-Т phone-number - Заменяет евсаре-последовательность \Т в тексте chat-еценария значением phone-number.
-U phone-number-2 - Заменяет еэсаре-последовательность \U в тексте chat-еценария значением phone-number-2.
-v - Режим подробной диагностики. В этом режиме информационные сообще- ния записываются посредством syslogd.
-V - Режим подробной диагностики с записью информационных сообщений в поток stderr. В главе 6 содержится пример использования этого ключа с pppd.
- t timeout - Устанавливает длительность ожидания строки. Если строка не получена за timeout секунд, ответ не посылается, а сценарий завершает работу (кроме тех случаев, когда определена альтернативная обработка). В случае альтернативной обработки (о которой мы поговорим ниже) удаленной системе передается определенная строка и наступает следующий интервал ожидания. Если и это не приводит к получению строки, сценарий прекращает работу с ненулевым кодом завершения. По умолчанию интервал timeout равен 45 секундам.
-f scriptfile - Сценарий chat читается из файла scriptfile, а не из командной строки. Файл может содержать произвольное количество пар ожидание/передача.
-r report file - chat производит запись информации, сгенерированной строками REPORT, в файл report file. По умолчанию строки REPORT записываются в поток stderr. Ключевое слово REPORT будет описано ниже.
В целях повышения надежности и функциональности сценариев в программе chat реализованы специальные ключевые слова, поддержка евсаре-последовательностей, а также возможность применения альтернативных пар передача/ ожидание. Прежде всего, рассмотрим семь самых важных ключевых слов.
Два ключевых слова отвечают за передачу специальных сигналов удаленной системе. Ключевое слово EOT приводит к посылке символа End of Transmission (конец передачи). В системах Unix это, как правило, символ конца файла, <Ctrl>+<D>. Ключевое слово BREAK приводит к посылке удаленной системе символа разрыва строки. Еще пять ключевых слов (TIMEOUT, ABORT, REPORT, CONNECT и SAY) определяют параметры работы собственно сценария.
Ключевое слово TIMEOUT позволяет указать длительность ожидания строки. При определении в тексте сценария данное значение может изменяться для каждой из ожидаемых строк. Предположим, мы даем удаленному серверу 30 секунд, чтобы отобразить приглашение Username>, но лишь 5 секунд, чтобы отобразить приглашение Password> после передачи имени пользователя. Задача решается при помощи следующей команды:
TIMEOUT 30 name> karen TIMEOUT 5 word> beach%PARTY
Ключевые слова ABORT и REPORT функционально схожи. Оба слова определяют строки, получение которых приводит к выполнению специальных действий. Ключевое слово ABORT определяет строки, получение которых вместо строки CONNECT от модема приводит к прерыванию работы сценария. Ключевое слово REPORT определяет подстроки, присутствие которых в сообщениях, полученных от последовательного порта, приводит к записи сообщений в поток stderr или файл отчета. Проиллюстрируем применение этих ключевых слов следующим примером:
REPORT CONNECT ABORT BUSY ABORT 'NO CARRIER' ABORT 'RING - NO ANSWER' say "np0M3B0flMTCfl noAiuwHeHMe k cepBepy ppp... "'• AT0T5551234 CONNECT \r name> karen word> beach*PARTY
Первая строка предписывает регистрировать в журнале все сообщения, полученные сценарием, которые содержат слово CONNECT. Если при запуске программы chat присутствовал ключ командной строки - г , сообщение заносится в файл, определенный аргументом ключа. В противном случае сообщение попадает в поток stderr. Назначение данной команды - отображать на терминале пользователя полученное от модема сообщение о подключении. Полное сообщение может выглядеть так: CONNECT 28, 800 LAPM/V; оно позволяет пользователю определить, какова скорость соединения и какой используется протокол передачи. Сообщение CONNECT означает успешное подключение. Следующие три строки сценария начинаются ключевым словом ABORT и связаны с сообщениями модема, означающими различные ошибки. Если от модема поступают сообщения BUSY, NO CARRIER или RING - NO ANSWER, работа сценария прерывается.
Ключевое слово SAY передает строку-аргумент на терминал пользователя. В данном случае мы говорим пользователю, что сценарий начал звонить. Последние четыре строки - это пары ожидание/передача, с которыми мы уже познакомились в этом разделе. Не ожидая получения строки (""), сценарий передает модему команду набора номера (ATDT). Сценарий ожидает получения строки CONNECT от модема и передает символ возврата каретки удаленному серверу; ожидает получения строки Username> от удаленного сервера и отвечает именем karen. Наконец, сценарий ожидает получения строки Password> от сервера и отвечает паролем beach%PARTY.
chat расширяет функциональность стандартных пар ожидание/передача альтернативными вариантами, повышающими надежность сценариев. Существует возможность задать альтернативную строку для передачи и альтернативное ожидаемое значение, которые используются, если истек временной интервал для основного ожидаемого значения. Альтернативные варианты в тексте сценария предваряются дефисами. Пример:
gin:-BREAK-gin: becca
В данном случае ожидается получение строки gin:, предполагается ответ строкой becca. Первая и последняя строки составляют стандартную пару ожидание/передача. Альтернативная пара передача/ожидание используется, если истек интервал ожидания и строка gin: не была получена. Тогда сценарий передает разрыв строки, обнуляет таймер и снова переходит к ожиданию строки gin:, поскольку именно такое поведение предписывается альтернативной парой передача/ожидание (-BREAK-gin:). Заметим, что для альтернативной пары передача значения выполняется до перехода в режим ожидания строки, то есть передача предшествует ожиданию. Еще один пример в серии наших сценариев:
name>—name > karen
Сценарий ожидает получения строки паше>. Если строка не получена, сценарий передает пустую строку (возврат каретки) и снова переходит к ожиданию строки паше>. Такое поведение определено альтернативной парой передача/ ожидание, --name>. Пара начинается с дефиса, который отмечает начало строки для передачи, но следующий символ также является дефисом и отмечает начало альтернативного ожидаемого значения. Строка для передачи, таким образом, отсутствует. Именно эта «пустая строка» приводит к передаче одного символа возврата каретки. Подобная конструкция, будучи менее прозрачной, применяется чаще, чем вариант со словом BREAK, описанный выше.
Помимо символа возврата каретки в chat существуют и другие escape-послвдовательности для приема и передачи специальных символов. Они перечислены в табл. А.2.
Таблица А.2. Escape-последовательности chat
Escape-последовательность | Значение |
\b | Забой |
\ | Передать без завершающего символа возврата каретки |
\d | Задержка передачи значения на одну секунду |
\к | Передать символ BREAK |
\n | Передать символ новой строки |
\N | Передать нулевой символ |
\P | Задержка передачи значения на одну десятую долю секунды |
\xd5 | Передать строку, но не фиксировать передачу в журнале |
\r | Возврат каретки |
\s | Символ пробела |
\T | Передать значение, полученное из командной строки chat в виде аргумента ключа -Т |
\t | Символ табуляции |
\u | Передать значение, полученное из командной строки chat в виде аргумента ключа -U |
\\ | Символ \ |
\ddd | ASCII-символ с восьмеричным значением ddd |
^С | Управляющий символ |
Все escape-последовательности, кроме той, что используется для ввода управляющих символов, начинаются с обратной косой черты (\). Управляющий символ состоит из символа и заглавной буквы. Например, управляющий символ X записывается в виде "X. Евсаре-последовательности, описанные в табл. А.2 с упоминанием передачи, могут использоваться только в строках для передачи; все прочие последовательности могут использоваться и для приема, и для передачи. Следующий пример иллюстрирует применение некоторых еэсаре-последовательностей:
"" \d\d^6\p^G\p\p^GnpocHnakicfl\scKopee!\nЛежебока\sты!
Не ожидая получения значения (""), сценарий делает паузу в две секунды (\d\d). Передает три символа ASCII BELL, которые в клавиатурной записи обозначаются как <Ctrl>+<G>, с интервалом в одну десятую долю секунды (~G\p~G\p\p~G). Передает строку Просыпайся скорее!. Переходит на новую строку (\п) и передает строку Лежебока ты!.
Из соображений безопасности сервер может перезванивать (callback) клиенту для создания соединения. Таким образом сервер проверяет, что звонок клиента поступил с допустимого телефонного номера. Механизм работает следующим образом:
- Клиент звонит на сервер и передает строку-идентификатор.
- Получив идентификатор, сервер разрывает соединение.
- Сервер использует идентификатор, чтобы определить телефонный номер клиента, и звонит по этому номеру.
- Клиент продолжает процесс регистрации на сервере.
Тот факт, что сервер разрывает соединение, может стать источником проблем для chat-сценария. Обычно разрыв коммутируемого канала приводит к безусловному завершению подключения. Для работы с саПЬаск-серверами существует команда HANGUP. Команда HANGUP OFF предотвращает завершение сценария регистрации в случае, если сервер разрывает соединение. Команда HANGUP OFF должна следовать непосредственно за командой, передающей серверу строкидентификатор. Когда сервер перезвонит и будет установлено соединение, воспользуйтесь командой HANGUP ON, чтобы вернуться к нормальной обработке разрыва подключения. По умолчанию (HANGUP ON) работа сценария прерывается, если произошел разрыв подключения.
В момент завершения работы chat-еценария устанавливается значение кода завершения. Код завершения - это числовое значение, обозначающее состояние сценария на момент завершения его работы. Ниже перечислены основные числовые коды и дана интерпретация каждого из них:
- 0 Сценарий завершился нормально.
- 1 Не удалось выполнить сценарий из-за некорректного параметра либо из-за переполнения буфера в процессе получения строки.
- 2 Работа сценария принудительно завершена из-за ошибки ввода/вывода либо по сигналу SIGINT/SIGTERM.
- 3 Работа программы завершена: истек интервал ожидания для строки.
- 4 и далее
Возникло условие, определенное командой ABORT. Числовое значение указывает, какое из условий выполнено. Первое условие, определенное командой ABORT, связано со значением 4; второе - со значением 5; третье - со значением 6 и т. д.
Коды завершения от 0 до 3 вполне прозрачны. Остальные значения легче понять на примере.
Ранее в этом разделе приводился пример сценария, содержавшего три команды ABORT: первая определяла поведение для события BUSY, вторая для события NO CARRIER, третья - для события RING - NO ANSWER. Если модем возвращает строку BUSY, сценарий завершает работу с кодом 4. Если модем возвращает строку RING - NO ANSWER, сценарий завершает работу с кодом 6. Значение кода завершения в каждом конкретном случае зависит от порядкового номера команды ABORT. Если бы другой пользователь переписал данный сценарий, расположив команду ABORT RING - NO ANSWER ранее всех прочих команд ABORT, завершение по событию RING - NO ANSWER приводило бы к получению кода 4, а не 6, как в нашем случае.