1fe552114SDavid Nugent /*-
2fe552114SDavid Nugent * Copyright (c) 1997
3fe552114SDavid Nugent * David L Nugent <davidn@blaze.net.au>.
4fe552114SDavid Nugent * All rights reserved.
5fe552114SDavid Nugent *
6fe552114SDavid Nugent *
7fe552114SDavid Nugent * Redistribution and use in source and binary forms, with or without
8fe552114SDavid Nugent * modification, is permitted provided that the following conditions
9fe552114SDavid Nugent * are met:
10fe552114SDavid Nugent * 1. Redistributions of source code must retain the above copyright
11fe552114SDavid Nugent * notice immediately at the beginning of the file, without modification,
12fe552114SDavid Nugent * this list of conditions, and the following disclaimer.
13fe552114SDavid Nugent * 2. Redistributions in binary form must reproduce the above copyright
14fe552114SDavid Nugent * notice, this list of conditions and the following disclaimer in the
15fe552114SDavid Nugent * documentation and/or other materials provided with the distribution.
16fe552114SDavid Nugent * 3. This work was done expressly for inclusion into FreeBSD. Other use
17fe552114SDavid Nugent * is permitted provided this notation is included.
18fe552114SDavid Nugent * 4. Absolutely no warranty of function or purpose is made by the authors.
19fe552114SDavid Nugent * 5. Modifications may be freely made to this file providing the above
20fe552114SDavid Nugent * conditions are met.
21fe552114SDavid Nugent *
22fe552114SDavid Nugent * Modem chat module - send/expect style functions for getty
23fe552114SDavid Nugent * For semi-intelligent modem handling.
24fe552114SDavid Nugent */
25fe552114SDavid Nugent
26391a2becSBruce Evans #include <sys/types.h>
27fe552114SDavid Nugent #include <sys/ioctl.h>
28fe552114SDavid Nugent #include <sys/utsname.h>
29391a2becSBruce Evans
30fe552114SDavid Nugent #include <ctype.h>
31fe552114SDavid Nugent #include <signal.h>
32fe552114SDavid Nugent #include <stdlib.h>
33fe552114SDavid Nugent #include <string.h>
34fe552114SDavid Nugent #include <syslog.h>
35fe552114SDavid Nugent #include <unistd.h>
36fe552114SDavid Nugent
37410f13a5SStefan Farfeleder #include "gettytab.h"
38fe552114SDavid Nugent #include "extern.h"
39fe552114SDavid Nugent
40fe552114SDavid Nugent #define PAUSE_CH (unsigned char)'\xff' /* pause kludge */
41fe552114SDavid Nugent
42fe552114SDavid Nugent #define CHATDEBUG_RECEIVE 0x01
43fe552114SDavid Nugent #define CHATDEBUG_SEND 0x02
44fe552114SDavid Nugent #define CHATDEBUG_EXPECT 0x04
45fe552114SDavid Nugent #define CHATDEBUG_MISC 0x08
46fe552114SDavid Nugent
47fe552114SDavid Nugent #define CHATDEBUG_DEFAULT 0
48fe552114SDavid Nugent #define CHAT_DEFAULT_TIMEOUT 10
49fe552114SDavid Nugent
50fe552114SDavid Nugent
51fe552114SDavid Nugent static int chat_debug = CHATDEBUG_DEFAULT;
52fe552114SDavid Nugent static int chat_alarm = CHAT_DEFAULT_TIMEOUT; /* Default */
53fe552114SDavid Nugent
54fe552114SDavid Nugent static volatile int alarmed = 0;
55fe552114SDavid Nugent
56fe552114SDavid Nugent
5795289b27SWarner Losh static void chat_alrm(int);
5895289b27SWarner Losh static int chat_unalarm(void);
59*8ad7a14aSDag-Erling Smørgrav static int getdigit(char **, int, int);
6095289b27SWarner Losh static char **read_chat(char **);
6195289b27SWarner Losh static char *cleanchr(char **, unsigned char);
62*8ad7a14aSDag-Erling Smørgrav static const char *cleanstr(const char *, int);
6395289b27SWarner Losh static const char *result(int);
6495289b27SWarner Losh static int chat_expect(const char *);
6595289b27SWarner Losh static int chat_send(char const *);
66fe552114SDavid Nugent
67fe552114SDavid Nugent
68fe552114SDavid Nugent /*
69fe552114SDavid Nugent * alarm signal handler
70fe552114SDavid Nugent * handle timeouts in read/write
71fe552114SDavid Nugent * change stdin to non-blocking mode to prevent
72fe552114SDavid Nugent * possible hang in read().
73fe552114SDavid Nugent */
74fe552114SDavid Nugent
75fe552114SDavid Nugent static void
chat_alrm(int signo __unused)769f8c3129SPhilippe Charnier chat_alrm(int signo __unused)
77fe552114SDavid Nugent {
78fe552114SDavid Nugent int on = 1;
79fe552114SDavid Nugent
80fe552114SDavid Nugent alarm(1);
81fe552114SDavid Nugent alarmed = 1;
82fe552114SDavid Nugent signal(SIGALRM, chat_alrm);
83fe552114SDavid Nugent ioctl(STDIN_FILENO, FIONBIO, &on);
84fe552114SDavid Nugent }
85fe552114SDavid Nugent
86fe552114SDavid Nugent
87fe552114SDavid Nugent /*
88fe552114SDavid Nugent * Turn back on blocking mode reset by chat_alrm()
89fe552114SDavid Nugent */
90fe552114SDavid Nugent
91fe552114SDavid Nugent static int
chat_unalarm(void)9295289b27SWarner Losh chat_unalarm(void)
93fe552114SDavid Nugent {
94fe552114SDavid Nugent int off = 0;
95fe552114SDavid Nugent return ioctl(STDIN_FILENO, FIONBIO, &off);
96fe552114SDavid Nugent }
97fe552114SDavid Nugent
98fe552114SDavid Nugent
99fe552114SDavid Nugent /*
100fe552114SDavid Nugent * convert a string of a given base (octal/hex) to binary
101fe552114SDavid Nugent */
102fe552114SDavid Nugent
103fe552114SDavid Nugent static int
getdigit(char ** ptr,int base,int max)104*8ad7a14aSDag-Erling Smørgrav getdigit(char **ptr, int base, int max)
105fe552114SDavid Nugent {
106fe552114SDavid Nugent int i, val = 0;
107fe552114SDavid Nugent char * q;
108fe552114SDavid Nugent
109fe552114SDavid Nugent static const char xdigits[] = "0123456789abcdef";
110fe552114SDavid Nugent
111fe552114SDavid Nugent for (i = 0, q = *ptr; i++ < max; ++q) {
112fe552114SDavid Nugent int sval;
113fe552114SDavid Nugent const char * s = strchr(xdigits, tolower(*q));
114fe552114SDavid Nugent
115fe552114SDavid Nugent if (s == NULL || (sval = s - xdigits) >= base)
116fe552114SDavid Nugent break;
117fe552114SDavid Nugent val = (val * base) + sval;
118fe552114SDavid Nugent }
119fe552114SDavid Nugent *ptr = q;
120fe552114SDavid Nugent return val;
121fe552114SDavid Nugent }
122fe552114SDavid Nugent
123fe552114SDavid Nugent
124fe552114SDavid Nugent /*
125fe552114SDavid Nugent * read_chat()
126fe552114SDavid Nugent * Convert a whitespace delimtied string into an array
127fe552114SDavid Nugent * of strings, being expect/send pairs
128fe552114SDavid Nugent */
129fe552114SDavid Nugent
130fe552114SDavid Nugent static char **
read_chat(char ** chatstr)13195289b27SWarner Losh read_chat(char **chatstr)
132fe552114SDavid Nugent {
133fe552114SDavid Nugent char *str = *chatstr;
134fe552114SDavid Nugent char **res = NULL;
135fe552114SDavid Nugent
136fe552114SDavid Nugent if (str != NULL) {
137fe552114SDavid Nugent char *tmp = NULL;
138fe552114SDavid Nugent int l;
139fe552114SDavid Nugent
140fe552114SDavid Nugent if ((l=strlen(str)) > 0 && (tmp=malloc(l + 1)) != NULL &&
14171bc4af6SStefan Eßer (res=malloc(((l + 1) / 2 + 1) * sizeof(char *))) != NULL) {
142fe552114SDavid Nugent static char ws[] = " \t";
143fe552114SDavid Nugent char * p;
144fe552114SDavid Nugent
145fe552114SDavid Nugent for (l = 0, p = strtok(strcpy(tmp, str), ws);
146fe552114SDavid Nugent p != NULL;
147fe552114SDavid Nugent p = strtok(NULL, ws))
148fe552114SDavid Nugent {
149*8ad7a14aSDag-Erling Smørgrav char *q, *r;
150fe552114SDavid Nugent
151fe552114SDavid Nugent /* Read escapes */
152*8ad7a14aSDag-Erling Smørgrav for (q = r = p; *r; ++q)
153fe552114SDavid Nugent {
154fe552114SDavid Nugent if (*q == '\\')
155fe552114SDavid Nugent {
156fe552114SDavid Nugent /* handle special escapes */
157fe552114SDavid Nugent switch (*++q)
158fe552114SDavid Nugent {
159fe552114SDavid Nugent case 'a': /* bell */
160fe552114SDavid Nugent *r++ = '\a';
161fe552114SDavid Nugent break;
162fe552114SDavid Nugent case 'r': /* cr */
163fe552114SDavid Nugent *r++ = '\r';
164fe552114SDavid Nugent break;
165fe552114SDavid Nugent case 'n': /* nl */
166fe552114SDavid Nugent *r++ = '\n';
167fe552114SDavid Nugent break;
168fe552114SDavid Nugent case 'f': /* ff */
169fe552114SDavid Nugent *r++ = '\f';
170fe552114SDavid Nugent break;
171fe552114SDavid Nugent case 'b': /* bs */
172fe552114SDavid Nugent *r++ = '\b';
173fe552114SDavid Nugent break;
174fe552114SDavid Nugent case 'e': /* esc */
175fe552114SDavid Nugent *r++ = 27;
176fe552114SDavid Nugent break;
177fe552114SDavid Nugent case 't': /* tab */
178fe552114SDavid Nugent *r++ = '\t';
179fe552114SDavid Nugent break;
180fe552114SDavid Nugent case 'p': /* pause */
181fe552114SDavid Nugent *r++ = PAUSE_CH;
182fe552114SDavid Nugent break;
183fe552114SDavid Nugent case 's':
184fe552114SDavid Nugent case 'S': /* space */
185fe552114SDavid Nugent *r++ = ' ';
186fe552114SDavid Nugent break;
187fe552114SDavid Nugent case 'x': /* hexdigit */
188fe552114SDavid Nugent ++q;
189fe552114SDavid Nugent *r++ = getdigit(&q, 16, 2);
190fe552114SDavid Nugent --q;
191fe552114SDavid Nugent break;
192fe552114SDavid Nugent case '0': /* octal */
193fe552114SDavid Nugent ++q;
194fe552114SDavid Nugent *r++ = getdigit(&q, 8, 3);
195fe552114SDavid Nugent --q;
196fe552114SDavid Nugent break;
197fe552114SDavid Nugent default: /* literal */
198fe552114SDavid Nugent *r++ = *q;
199fe552114SDavid Nugent break;
200fe552114SDavid Nugent case 0: /* not past eos */
201fe552114SDavid Nugent --q;
202fe552114SDavid Nugent break;
203fe552114SDavid Nugent }
204fe552114SDavid Nugent } else {
205fe552114SDavid Nugent /* copy standard character */
206b92f6bd2SDavid Nugent *r++ = *q;
207fe552114SDavid Nugent }
208fe552114SDavid Nugent }
209fe552114SDavid Nugent
210fe552114SDavid Nugent /* Remove surrounding quotes, if any
211fe552114SDavid Nugent */
212fe552114SDavid Nugent if (*p == '"' || *p == '\'') {
213fe552114SDavid Nugent q = strrchr(p+1, *p);
214fe552114SDavid Nugent if (q != NULL && *q == *p && q[1] == '\0') {
215fe552114SDavid Nugent *q = '\0';
21671bc4af6SStefan Eßer p++;
217fe552114SDavid Nugent }
218fe552114SDavid Nugent }
219fe552114SDavid Nugent
220fe552114SDavid Nugent res[l++] = p;
221fe552114SDavid Nugent }
222fe552114SDavid Nugent res[l] = NULL;
223fe552114SDavid Nugent *chatstr = tmp;
224fe552114SDavid Nugent return res;
225fe552114SDavid Nugent }
226fe552114SDavid Nugent free(tmp);
227fe552114SDavid Nugent }
228fe552114SDavid Nugent return res;
229fe552114SDavid Nugent }
230fe552114SDavid Nugent
231fe552114SDavid Nugent
232fe552114SDavid Nugent /*
233fe552114SDavid Nugent * clean a character for display (ctrl/meta character)
234fe552114SDavid Nugent */
235fe552114SDavid Nugent
236fe552114SDavid Nugent static char *
cleanchr(char ** buf,unsigned char ch)23795289b27SWarner Losh cleanchr(char **buf, unsigned char ch)
238fe552114SDavid Nugent {
239fe552114SDavid Nugent int l;
240fe552114SDavid Nugent static char tmpbuf[5];
241fe552114SDavid Nugent char * tmp = buf ? *buf : tmpbuf;
242fe552114SDavid Nugent
243fe552114SDavid Nugent if (ch & 0x80) {
244fe552114SDavid Nugent strcpy(tmp, "M-");
245fe552114SDavid Nugent l = 2;
246fe552114SDavid Nugent ch &= 0x7f;
247fe552114SDavid Nugent } else
248fe552114SDavid Nugent l = 0;
249fe552114SDavid Nugent
250fe552114SDavid Nugent if (ch < 32) {
251fe552114SDavid Nugent tmp[l++] = '^';
252fe552114SDavid Nugent tmp[l++] = ch + '@';
253fe552114SDavid Nugent } else if (ch == 127) {
254fe552114SDavid Nugent tmp[l++] = '^';
255fe552114SDavid Nugent tmp[l++] = '?';
256fe552114SDavid Nugent } else
257fe552114SDavid Nugent tmp[l++] = ch;
258fe552114SDavid Nugent tmp[l] = '\0';
259fe552114SDavid Nugent
260fe552114SDavid Nugent if (buf)
261fe552114SDavid Nugent *buf = tmp + l;
262fe552114SDavid Nugent return tmp;
263fe552114SDavid Nugent }
264fe552114SDavid Nugent
265fe552114SDavid Nugent
266fe552114SDavid Nugent /*
267fe552114SDavid Nugent * clean a string for display (ctrl/meta characters)
268fe552114SDavid Nugent */
269fe552114SDavid Nugent
27018587b84SEdward Tomasz Napierala static const char *
cleanstr(const char * s,int l)271*8ad7a14aSDag-Erling Smørgrav cleanstr(const char *s, int l)
272fe552114SDavid Nugent {
273*8ad7a14aSDag-Erling Smørgrav static char * tmp = NULL;
274fe552114SDavid Nugent static int tmplen = 0;
275fe552114SDavid Nugent
276fe552114SDavid Nugent if (tmplen < l * 4 + 1)
277fe552114SDavid Nugent tmp = realloc(tmp, tmplen = l * 4 + 1);
278fe552114SDavid Nugent
279fe552114SDavid Nugent if (tmp == NULL) {
280fe552114SDavid Nugent tmplen = 0;
28118587b84SEdward Tomasz Napierala return "(mem alloc error)";
282fe552114SDavid Nugent } else {
283fe552114SDavid Nugent int i = 0;
284fe552114SDavid Nugent char * p = tmp;
285fe552114SDavid Nugent
286fe552114SDavid Nugent while (i < l)
287fe552114SDavid Nugent cleanchr(&p, s[i++]);
288fe552114SDavid Nugent *p = '\0';
289fe552114SDavid Nugent }
290fe552114SDavid Nugent
291fe552114SDavid Nugent return tmp;
292fe552114SDavid Nugent }
293fe552114SDavid Nugent
294fe552114SDavid Nugent
295fe552114SDavid Nugent /*
296d64ada50SJens Schweikhardt * return result as a pseudo-english word
297fe552114SDavid Nugent */
298fe552114SDavid Nugent
299fe552114SDavid Nugent static const char *
result(int r)30095289b27SWarner Losh result(int r)
301fe552114SDavid Nugent {
302fe552114SDavid Nugent static const char * results[] = {
303fe552114SDavid Nugent "OK", "MEMERROR", "IOERROR", "TIMEOUT"
304fe552114SDavid Nugent };
305fe552114SDavid Nugent return results[r & 3];
306fe552114SDavid Nugent }
307fe552114SDavid Nugent
308fe552114SDavid Nugent
309fe552114SDavid Nugent /*
310fe552114SDavid Nugent * chat_expect()
311fe552114SDavid Nugent * scan input for an expected string
312fe552114SDavid Nugent */
313fe552114SDavid Nugent
314fe552114SDavid Nugent static int
chat_expect(const char * str)31595289b27SWarner Losh chat_expect(const char *str)
316fe552114SDavid Nugent {
317fe552114SDavid Nugent int len, r = 0;
318fe552114SDavid Nugent
319fe552114SDavid Nugent if (chat_debug & CHATDEBUG_EXPECT)
320fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_expect '%s'", cleanstr(str, strlen(str)));
321fe552114SDavid Nugent
322fe552114SDavid Nugent if ((len = strlen(str)) > 0) {
323fe552114SDavid Nugent int i = 0;
324fe552114SDavid Nugent char * got;
325fe552114SDavid Nugent
326fe552114SDavid Nugent if ((got = malloc(len + 1)) == NULL)
327fe552114SDavid Nugent r = 1;
328fe552114SDavid Nugent else {
329fe552114SDavid Nugent
330fe552114SDavid Nugent memset(got, 0, len+1);
331fe552114SDavid Nugent alarm(chat_alarm);
332fe552114SDavid Nugent alarmed = 0;
333fe552114SDavid Nugent
334fe552114SDavid Nugent while (r == 0 && i < len) {
335fe552114SDavid Nugent if (alarmed)
336fe552114SDavid Nugent r = 3;
337fe552114SDavid Nugent else {
338fe552114SDavid Nugent unsigned char ch;
339fe552114SDavid Nugent
340fe552114SDavid Nugent if (read(STDIN_FILENO, &ch, 1) == 1) {
341fe552114SDavid Nugent
342fe552114SDavid Nugent if (chat_debug & CHATDEBUG_RECEIVE)
343fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_recv '%s' m=%d",
344fe552114SDavid Nugent cleanchr(NULL, ch), i);
345fe552114SDavid Nugent
346fe552114SDavid Nugent if (ch == str[i])
347fe552114SDavid Nugent got[i++] = ch;
348fe552114SDavid Nugent else if (i > 0) {
349fe552114SDavid Nugent int j = 1;
350fe552114SDavid Nugent
351fe552114SDavid Nugent /* See if we can resync on a
352fe552114SDavid Nugent * partial match in our buffer
353fe552114SDavid Nugent */
3542dc8d58fSBruce Evans while (j < i && memcmp(got + j, str, i - j) != 0)
355fe552114SDavid Nugent j++;
356fe552114SDavid Nugent if (j < i)
357fe552114SDavid Nugent memcpy(got, got + j, i - j);
358fe552114SDavid Nugent i -= j;
359fe552114SDavid Nugent }
360fe552114SDavid Nugent } else
361fe552114SDavid Nugent r = alarmed ? 3 : 2;
362fe552114SDavid Nugent }
363fe552114SDavid Nugent }
364fe552114SDavid Nugent alarm(0);
365fe552114SDavid Nugent chat_unalarm();
366fe552114SDavid Nugent alarmed = 0;
367fe552114SDavid Nugent free(got);
368fe552114SDavid Nugent }
369fe552114SDavid Nugent }
370fe552114SDavid Nugent
371fe552114SDavid Nugent if (chat_debug & CHATDEBUG_EXPECT)
372fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_expect %s", result(r));
373fe552114SDavid Nugent
374fe552114SDavid Nugent return r;
375fe552114SDavid Nugent }
376fe552114SDavid Nugent
377fe552114SDavid Nugent
378fe552114SDavid Nugent /*
379fe552114SDavid Nugent * chat_send()
380fe552114SDavid Nugent * send a chat string
381fe552114SDavid Nugent */
382fe552114SDavid Nugent
383fe552114SDavid Nugent static int
chat_send(char const * str)38495289b27SWarner Losh chat_send(char const *str)
385fe552114SDavid Nugent {
386fe552114SDavid Nugent int r = 0;
387fe552114SDavid Nugent
38850541c92SDimitry Andric if (chat_debug & CHATDEBUG_SEND)
389fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_send '%s'", cleanstr(str, strlen(str)));
390fe552114SDavid Nugent
391fe552114SDavid Nugent if (*str) {
392fe552114SDavid Nugent alarm(chat_alarm);
393fe552114SDavid Nugent alarmed = 0;
394fe552114SDavid Nugent while (r == 0 && *str)
395fe552114SDavid Nugent {
396fe552114SDavid Nugent unsigned char ch = (unsigned char)*str++;
397fe552114SDavid Nugent
398fe552114SDavid Nugent if (alarmed)
399fe552114SDavid Nugent r = 3;
400fe552114SDavid Nugent else if (ch == PAUSE_CH)
401fe552114SDavid Nugent usleep(500000); /* 1/2 second */
402fe552114SDavid Nugent else {
403fe552114SDavid Nugent usleep(10000); /* be kind to modem */
404fe552114SDavid Nugent if (write(STDOUT_FILENO, &ch, 1) != 1)
405fe552114SDavid Nugent r = alarmed ? 3 : 2;
406fe552114SDavid Nugent }
407fe552114SDavid Nugent }
408fe552114SDavid Nugent alarm(0);
409fe552114SDavid Nugent chat_unalarm();
410fe552114SDavid Nugent alarmed = 0;
411fe552114SDavid Nugent }
412fe552114SDavid Nugent
413fe552114SDavid Nugent if (chat_debug & CHATDEBUG_SEND)
414fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_send %s", result(r));
415fe552114SDavid Nugent
416fe552114SDavid Nugent return r;
417fe552114SDavid Nugent }
418fe552114SDavid Nugent
419fe552114SDavid Nugent
420fe552114SDavid Nugent /*
421fe552114SDavid Nugent * getty_chat()
422fe552114SDavid Nugent *
423fe552114SDavid Nugent * Termination codes:
424fe552114SDavid Nugent * -1 - no script supplied
425fe552114SDavid Nugent * 0 - script terminated correctly
426fe552114SDavid Nugent * 1 - invalid argument, expect string too large, etc.
427fe552114SDavid Nugent * 2 - error on an I/O operation or fatal error condition
428fe552114SDavid Nugent * 3 - timeout waiting for a simple string
429fe552114SDavid Nugent *
430fe552114SDavid Nugent * Parameters:
431fe552114SDavid Nugent * char *scrstr - unparsed chat script
432fe552114SDavid Nugent * timeout - seconds timeout
433fe552114SDavid Nugent * debug - debug value (bitmask)
434fe552114SDavid Nugent */
435fe552114SDavid Nugent
436fe552114SDavid Nugent int
getty_chat(char * scrstr,int timeout,int debug)43795289b27SWarner Losh getty_chat(char *scrstr, int timeout, int debug)
438fe552114SDavid Nugent {
439fe552114SDavid Nugent int r = -1;
440fe552114SDavid Nugent
441fe552114SDavid Nugent chat_alarm = timeout ? timeout : CHAT_DEFAULT_TIMEOUT;
442fe552114SDavid Nugent chat_debug = debug;
443fe552114SDavid Nugent
444fe552114SDavid Nugent if (scrstr != NULL) {
445fe552114SDavid Nugent char **script;
446fe552114SDavid Nugent
447fe552114SDavid Nugent if (chat_debug & CHATDEBUG_MISC)
448fe552114SDavid Nugent syslog(LOG_DEBUG, "getty_chat script='%s'", scrstr);
449fe552114SDavid Nugent
450fe552114SDavid Nugent if ((script = read_chat(&scrstr)) != NULL) {
451fe552114SDavid Nugent int i = r = 0;
452fe552114SDavid Nugent int off = 0;
453fe552114SDavid Nugent sig_t old_alarm;
454fe552114SDavid Nugent
45526015440SDavid Nugent /*
45626015440SDavid Nugent * We need to be in raw mode for all this
45726015440SDavid Nugent * Rely on caller...
458fe552114SDavid Nugent */
459fe552114SDavid Nugent
460fe552114SDavid Nugent old_alarm = signal(SIGALRM, chat_alrm);
461fe552114SDavid Nugent chat_unalarm(); /* Force blocking mode at start */
462fe552114SDavid Nugent
463fe552114SDavid Nugent /*
464fe552114SDavid Nugent * This is the send/expect loop
465fe552114SDavid Nugent */
466fe552114SDavid Nugent while (r == 0 && script[i] != NULL)
467fe552114SDavid Nugent if ((r = chat_expect(script[i++])) == 0 && script[i] != NULL)
468fe552114SDavid Nugent r = chat_send(script[i++]);
469fe552114SDavid Nugent
470fe552114SDavid Nugent signal(SIGALRM, old_alarm);
471fe552114SDavid Nugent free(script);
472fe552114SDavid Nugent free(scrstr);
473fe552114SDavid Nugent
47426015440SDavid Nugent /*
47526015440SDavid Nugent * Ensure stdin is in blocking mode
476fe552114SDavid Nugent */
477fe552114SDavid Nugent ioctl(STDIN_FILENO, FIONBIO, &off);
478fe552114SDavid Nugent }
479fe552114SDavid Nugent
480fe552114SDavid Nugent if (chat_debug & CHATDEBUG_MISC)
481fe552114SDavid Nugent syslog(LOG_DEBUG, "getty_chat %s", result(r));
482fe552114SDavid Nugent
483fe552114SDavid Nugent }
484fe552114SDavid Nugent return r;
485fe552114SDavid Nugent }
486