The pppd package comes along with a similar program called chat, which lets you specify a UUCP-style chat script. Basically, a chat script consists of an alternating sequence of strings that we expect to receive from the remote system, and the answers we are to send. We will call the expect and send strings, respectively. This is a typical excerpt from a chat script;
ogin: b1ff ssword: s3kr3t
This tells chat to wait for the remote system to send the login
prompt, and return the login name b1ff. We only wait for
ogin: so that it doesn't matter if the login prompt starts with
an uppercase or lowercase l, or if it arrives garbled. The following
string is an expect-string again that makes chat wait for the
password prompt, and send our password in response.
This is basically all that chat scripts are about. A complete script to dial up a PPP server would, of course, also have to include the appropriate modem commands. Assume your modem understands the Hayes command set, and the server's telephone number was 318714. The complete chat invocation to establish a connection with c3po would then be
$ chat -v '' ATZ OK ATDT318714 CONNECT '' ogin: ppp word: GaGariN
By definition, the first string must be an expect string, but as the
modem won't say anything before we have kicked it, we make chat
skip the first expect by specifying an empty string. We go on and send
ATZ, the reset command for Hayes-compatible modems, and wait for
its response (OK). The next string sends the dial command along
with the phone number to chat, and expects the CONNECT
message in response. This is followed by an empty string again, because
we don't want to send anything now, but rather wait for the login
prompt. The remainder of the chat script works exactly as described
above.
The -v option makes chat log all activities to the
syslog daemon's local2 facility.
Specifying the chat script on the command line bears a certain risk, because users can view a process' command line with the ps command. You can avoid this by putting the chat script in a file, say dial-c3po. You make chat read the script from the file instead of the command line by giving it the -f option, followed by the file name. The complete pppd incantation would now look like this:
# pppd connect "chat -f dial-c3po" /dev/cua3 38400 -detach \
crtscts modem defaultroute
Beside the connect option that specifies the dial-up script,
we have added two more options to the command line: -detach,
which tells pppd not to detach from the console and become a
background process. The modem keyword makes it perform some
modem-specific actions on the serial device, like hanging up the line
before and after the call. If you don't use this keyword, pppd
will not monitor the port's DCD line, and will therefore not detect if
the remote end hangs up unexpectedly.
The examples shown above were rather simple; chat allows for much more complex chat scripts. One very useful feature is the ability to specify strings on which to abort the chat with an error. Typical abort strings are messages like BUSY, or NO CARRIER, that your modem usually generates when the called number is busy, or doesn't pick up the phone. To make chat recognize these immediately, rather than timing out, you can specify them at the beginning of the script using the ABORT keyword:
$ chat -v ABORT BUSY ABORT 'NO CARRIER' '' ATZ OK ...
In a similar fashion, you may change the timeout value for parts of the
chat scripts by inserting TIMEOUT options. For details, please
check the chat(8) manual page.
Sometimes, you'd also want to have some sort of conditional execution of parts of the chat script. For instance, when you don't receive the remote end's login prompt, you might want to send a BREAK, or a carriage return. You can achieve this by appending a sub-script to an expect string. It consists of a sequence of send- and expect-strings, just like the overall script itself, which are separated by hyphens. The sub-script is executed whenever the expected string they are appended to is not received in time. In the example above, we would modify the chat script as follows:
ogin:-BREAK-ogin: ppp ssword: GaGariN
Now, when chat doesn't see the remote system send the login
prompt, the sub-script is executed by first sending a BREAK, and then
waiting for the login prompt again. If the prompt now appears, the
script continues as usual, otherwise it will terminate with an error.