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, как в нашем случае.