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 269f8c3129SPhilippe Charnier #include <sys/cdefs.h> 279f8c3129SPhilippe Charnier __FBSDID("$FreeBSD$"); 28d748864dSPhilippe Charnier 29391a2becSBruce Evans #include <sys/types.h> 30fe552114SDavid Nugent #include <sys/ioctl.h> 31fe552114SDavid Nugent #include <sys/utsname.h> 32391a2becSBruce Evans 33fe552114SDavid Nugent #include <ctype.h> 34fe552114SDavid Nugent #include <signal.h> 35fe552114SDavid Nugent #include <stdlib.h> 36fe552114SDavid Nugent #include <string.h> 37fe552114SDavid Nugent #include <syslog.h> 38fe552114SDavid Nugent #include <unistd.h> 39fe552114SDavid Nugent 40410f13a5SStefan Farfeleder #include "gettytab.h" 41fe552114SDavid Nugent #include "extern.h" 42fe552114SDavid Nugent 43fe552114SDavid Nugent #define PAUSE_CH (unsigned char)'\xff' /* pause kludge */ 44fe552114SDavid Nugent 45fe552114SDavid Nugent #define CHATDEBUG_RECEIVE 0x01 46fe552114SDavid Nugent #define CHATDEBUG_SEND 0x02 47fe552114SDavid Nugent #define CHATDEBUG_EXPECT 0x04 48fe552114SDavid Nugent #define CHATDEBUG_MISC 0x08 49fe552114SDavid Nugent 50fe552114SDavid Nugent #define CHATDEBUG_DEFAULT 0 51fe552114SDavid Nugent #define CHAT_DEFAULT_TIMEOUT 10 52fe552114SDavid Nugent 53fe552114SDavid Nugent 54fe552114SDavid Nugent static int chat_debug = CHATDEBUG_DEFAULT; 55fe552114SDavid Nugent static int chat_alarm = CHAT_DEFAULT_TIMEOUT; /* Default */ 56fe552114SDavid Nugent 57fe552114SDavid Nugent static volatile int alarmed = 0; 58fe552114SDavid Nugent 59fe552114SDavid Nugent 6095289b27SWarner Losh static void chat_alrm(int); 6195289b27SWarner Losh static int chat_unalarm(void); 6295289b27SWarner Losh static int getdigit(unsigned char **, int, int); 6395289b27SWarner Losh static char **read_chat(char **); 6495289b27SWarner Losh static char *cleanchr(char **, unsigned char); 65*18587b84SEdward Tomasz Napierala static const char *cleanstr(const unsigned char *, int); 6695289b27SWarner Losh static const char *result(int); 6795289b27SWarner Losh static int chat_expect(const char *); 6895289b27SWarner Losh static int chat_send(char const *); 69fe552114SDavid Nugent 70fe552114SDavid Nugent 71fe552114SDavid Nugent /* 72fe552114SDavid Nugent * alarm signal handler 73fe552114SDavid Nugent * handle timeouts in read/write 74fe552114SDavid Nugent * change stdin to non-blocking mode to prevent 75fe552114SDavid Nugent * possible hang in read(). 76fe552114SDavid Nugent */ 77fe552114SDavid Nugent 78fe552114SDavid Nugent static void 799f8c3129SPhilippe Charnier chat_alrm(int signo __unused) 80fe552114SDavid Nugent { 81fe552114SDavid Nugent int on = 1; 82fe552114SDavid Nugent 83fe552114SDavid Nugent alarm(1); 84fe552114SDavid Nugent alarmed = 1; 85fe552114SDavid Nugent signal(SIGALRM, chat_alrm); 86fe552114SDavid Nugent ioctl(STDIN_FILENO, FIONBIO, &on); 87fe552114SDavid Nugent } 88fe552114SDavid Nugent 89fe552114SDavid Nugent 90fe552114SDavid Nugent /* 91fe552114SDavid Nugent * Turn back on blocking mode reset by chat_alrm() 92fe552114SDavid Nugent */ 93fe552114SDavid Nugent 94fe552114SDavid Nugent static int 9595289b27SWarner Losh chat_unalarm(void) 96fe552114SDavid Nugent { 97fe552114SDavid Nugent int off = 0; 98fe552114SDavid Nugent return ioctl(STDIN_FILENO, FIONBIO, &off); 99fe552114SDavid Nugent } 100fe552114SDavid Nugent 101fe552114SDavid Nugent 102fe552114SDavid Nugent /* 103fe552114SDavid Nugent * convert a string of a given base (octal/hex) to binary 104fe552114SDavid Nugent */ 105fe552114SDavid Nugent 106fe552114SDavid Nugent static int 10795289b27SWarner Losh getdigit(unsigned char **ptr, int base, int max) 108fe552114SDavid Nugent { 109fe552114SDavid Nugent int i, val = 0; 110fe552114SDavid Nugent char * q; 111fe552114SDavid Nugent 112fe552114SDavid Nugent static const char xdigits[] = "0123456789abcdef"; 113fe552114SDavid Nugent 114fe552114SDavid Nugent for (i = 0, q = *ptr; i++ < max; ++q) { 115fe552114SDavid Nugent int sval; 116fe552114SDavid Nugent const char * s = strchr(xdigits, tolower(*q)); 117fe552114SDavid Nugent 118fe552114SDavid Nugent if (s == NULL || (sval = s - xdigits) >= base) 119fe552114SDavid Nugent break; 120fe552114SDavid Nugent val = (val * base) + sval; 121fe552114SDavid Nugent } 122fe552114SDavid Nugent *ptr = q; 123fe552114SDavid Nugent return val; 124fe552114SDavid Nugent } 125fe552114SDavid Nugent 126fe552114SDavid Nugent 127fe552114SDavid Nugent /* 128fe552114SDavid Nugent * read_chat() 129fe552114SDavid Nugent * Convert a whitespace delimtied string into an array 130fe552114SDavid Nugent * of strings, being expect/send pairs 131fe552114SDavid Nugent */ 132fe552114SDavid Nugent 133fe552114SDavid Nugent static char ** 13495289b27SWarner Losh read_chat(char **chatstr) 135fe552114SDavid Nugent { 136fe552114SDavid Nugent char *str = *chatstr; 137fe552114SDavid Nugent char **res = NULL; 138fe552114SDavid Nugent 139fe552114SDavid Nugent if (str != NULL) { 140fe552114SDavid Nugent char *tmp = NULL; 141fe552114SDavid Nugent int l; 142fe552114SDavid Nugent 143fe552114SDavid Nugent if ((l=strlen(str)) > 0 && (tmp=malloc(l + 1)) != NULL && 144fe552114SDavid Nugent (res=malloc((l / 2 + 1) * sizeof(char *))) != NULL) { 145fe552114SDavid Nugent static char ws[] = " \t"; 146fe552114SDavid Nugent char * p; 147fe552114SDavid Nugent 148fe552114SDavid Nugent for (l = 0, p = strtok(strcpy(tmp, str), ws); 149fe552114SDavid Nugent p != NULL; 150fe552114SDavid Nugent p = strtok(NULL, ws)) 151fe552114SDavid Nugent { 152fe552114SDavid Nugent unsigned char *q, *r; 153fe552114SDavid Nugent 154fe552114SDavid Nugent /* Read escapes */ 155fe552114SDavid Nugent for (q = r = (unsigned char *)p; *r; ++q) 156fe552114SDavid Nugent { 157fe552114SDavid Nugent if (*q == '\\') 158fe552114SDavid Nugent { 159fe552114SDavid Nugent /* handle special escapes */ 160fe552114SDavid Nugent switch (*++q) 161fe552114SDavid Nugent { 162fe552114SDavid Nugent case 'a': /* bell */ 163fe552114SDavid Nugent *r++ = '\a'; 164fe552114SDavid Nugent break; 165fe552114SDavid Nugent case 'r': /* cr */ 166fe552114SDavid Nugent *r++ = '\r'; 167fe552114SDavid Nugent break; 168fe552114SDavid Nugent case 'n': /* nl */ 169fe552114SDavid Nugent *r++ = '\n'; 170fe552114SDavid Nugent break; 171fe552114SDavid Nugent case 'f': /* ff */ 172fe552114SDavid Nugent *r++ = '\f'; 173fe552114SDavid Nugent break; 174fe552114SDavid Nugent case 'b': /* bs */ 175fe552114SDavid Nugent *r++ = '\b'; 176fe552114SDavid Nugent break; 177fe552114SDavid Nugent case 'e': /* esc */ 178fe552114SDavid Nugent *r++ = 27; 179fe552114SDavid Nugent break; 180fe552114SDavid Nugent case 't': /* tab */ 181fe552114SDavid Nugent *r++ = '\t'; 182fe552114SDavid Nugent break; 183fe552114SDavid Nugent case 'p': /* pause */ 184fe552114SDavid Nugent *r++ = PAUSE_CH; 185fe552114SDavid Nugent break; 186fe552114SDavid Nugent case 's': 187fe552114SDavid Nugent case 'S': /* space */ 188fe552114SDavid Nugent *r++ = ' '; 189fe552114SDavid Nugent break; 190fe552114SDavid Nugent case 'x': /* hexdigit */ 191fe552114SDavid Nugent ++q; 192fe552114SDavid Nugent *r++ = getdigit(&q, 16, 2); 193fe552114SDavid Nugent --q; 194fe552114SDavid Nugent break; 195fe552114SDavid Nugent case '0': /* octal */ 196fe552114SDavid Nugent ++q; 197fe552114SDavid Nugent *r++ = getdigit(&q, 8, 3); 198fe552114SDavid Nugent --q; 199fe552114SDavid Nugent break; 200fe552114SDavid Nugent default: /* literal */ 201fe552114SDavid Nugent *r++ = *q; 202fe552114SDavid Nugent break; 203fe552114SDavid Nugent case 0: /* not past eos */ 204fe552114SDavid Nugent --q; 205fe552114SDavid Nugent break; 206fe552114SDavid Nugent } 207fe552114SDavid Nugent } else { 208fe552114SDavid Nugent /* copy standard character */ 209b92f6bd2SDavid Nugent *r++ = *q; 210fe552114SDavid Nugent } 211fe552114SDavid Nugent } 212fe552114SDavid Nugent 213fe552114SDavid Nugent /* Remove surrounding quotes, if any 214fe552114SDavid Nugent */ 215fe552114SDavid Nugent if (*p == '"' || *p == '\'') { 216fe552114SDavid Nugent q = strrchr(p+1, *p); 217fe552114SDavid Nugent if (q != NULL && *q == *p && q[1] == '\0') { 218fe552114SDavid Nugent *q = '\0'; 219fe552114SDavid Nugent strcpy(p, p+1); 220fe552114SDavid Nugent } 221fe552114SDavid Nugent } 222fe552114SDavid Nugent 223fe552114SDavid Nugent res[l++] = p; 224fe552114SDavid Nugent } 225fe552114SDavid Nugent res[l] = NULL; 226fe552114SDavid Nugent *chatstr = tmp; 227fe552114SDavid Nugent return res; 228fe552114SDavid Nugent } 229fe552114SDavid Nugent free(tmp); 230fe552114SDavid Nugent } 231fe552114SDavid Nugent return res; 232fe552114SDavid Nugent } 233fe552114SDavid Nugent 234fe552114SDavid Nugent 235fe552114SDavid Nugent /* 236fe552114SDavid Nugent * clean a character for display (ctrl/meta character) 237fe552114SDavid Nugent */ 238fe552114SDavid Nugent 239fe552114SDavid Nugent static char * 24095289b27SWarner Losh cleanchr(char **buf, unsigned char ch) 241fe552114SDavid Nugent { 242fe552114SDavid Nugent int l; 243fe552114SDavid Nugent static char tmpbuf[5]; 244fe552114SDavid Nugent char * tmp = buf ? *buf : tmpbuf; 245fe552114SDavid Nugent 246fe552114SDavid Nugent if (ch & 0x80) { 247fe552114SDavid Nugent strcpy(tmp, "M-"); 248fe552114SDavid Nugent l = 2; 249fe552114SDavid Nugent ch &= 0x7f; 250fe552114SDavid Nugent } else 251fe552114SDavid Nugent l = 0; 252fe552114SDavid Nugent 253fe552114SDavid Nugent if (ch < 32) { 254fe552114SDavid Nugent tmp[l++] = '^'; 255fe552114SDavid Nugent tmp[l++] = ch + '@'; 256fe552114SDavid Nugent } else if (ch == 127) { 257fe552114SDavid Nugent tmp[l++] = '^'; 258fe552114SDavid Nugent tmp[l++] = '?'; 259fe552114SDavid Nugent } else 260fe552114SDavid Nugent tmp[l++] = ch; 261fe552114SDavid Nugent tmp[l] = '\0'; 262fe552114SDavid Nugent 263fe552114SDavid Nugent if (buf) 264fe552114SDavid Nugent *buf = tmp + l; 265fe552114SDavid Nugent return tmp; 266fe552114SDavid Nugent } 267fe552114SDavid Nugent 268fe552114SDavid Nugent 269fe552114SDavid Nugent /* 270fe552114SDavid Nugent * clean a string for display (ctrl/meta characters) 271fe552114SDavid Nugent */ 272fe552114SDavid Nugent 273*18587b84SEdward Tomasz Napierala static const char * 27495289b27SWarner Losh cleanstr(const unsigned char *s, int l) 275fe552114SDavid Nugent { 276fe552114SDavid Nugent static unsigned char * tmp = NULL; 277fe552114SDavid Nugent static int tmplen = 0; 278fe552114SDavid Nugent 279fe552114SDavid Nugent if (tmplen < l * 4 + 1) 280fe552114SDavid Nugent tmp = realloc(tmp, tmplen = l * 4 + 1); 281fe552114SDavid Nugent 282fe552114SDavid Nugent if (tmp == NULL) { 283fe552114SDavid Nugent tmplen = 0; 284*18587b84SEdward Tomasz Napierala return "(mem alloc error)"; 285fe552114SDavid Nugent } else { 286fe552114SDavid Nugent int i = 0; 287fe552114SDavid Nugent char * p = tmp; 288fe552114SDavid Nugent 289fe552114SDavid Nugent while (i < l) 290fe552114SDavid Nugent cleanchr(&p, s[i++]); 291fe552114SDavid Nugent *p = '\0'; 292fe552114SDavid Nugent } 293fe552114SDavid Nugent 294fe552114SDavid Nugent return tmp; 295fe552114SDavid Nugent } 296fe552114SDavid Nugent 297fe552114SDavid Nugent 298fe552114SDavid Nugent /* 299d64ada50SJens Schweikhardt * return result as a pseudo-english word 300fe552114SDavid Nugent */ 301fe552114SDavid Nugent 302fe552114SDavid Nugent static const char * 30395289b27SWarner Losh result(int r) 304fe552114SDavid Nugent { 305fe552114SDavid Nugent static const char * results[] = { 306fe552114SDavid Nugent "OK", "MEMERROR", "IOERROR", "TIMEOUT" 307fe552114SDavid Nugent }; 308fe552114SDavid Nugent return results[r & 3]; 309fe552114SDavid Nugent } 310fe552114SDavid Nugent 311fe552114SDavid Nugent 312fe552114SDavid Nugent /* 313fe552114SDavid Nugent * chat_expect() 314fe552114SDavid Nugent * scan input for an expected string 315fe552114SDavid Nugent */ 316fe552114SDavid Nugent 317fe552114SDavid Nugent static int 31895289b27SWarner Losh chat_expect(const char *str) 319fe552114SDavid Nugent { 320fe552114SDavid Nugent int len, r = 0; 321fe552114SDavid Nugent 322fe552114SDavid Nugent if (chat_debug & CHATDEBUG_EXPECT) 323fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_expect '%s'", cleanstr(str, strlen(str))); 324fe552114SDavid Nugent 325fe552114SDavid Nugent if ((len = strlen(str)) > 0) { 326fe552114SDavid Nugent int i = 0; 327fe552114SDavid Nugent char * got; 328fe552114SDavid Nugent 329fe552114SDavid Nugent if ((got = malloc(len + 1)) == NULL) 330fe552114SDavid Nugent r = 1; 331fe552114SDavid Nugent else { 332fe552114SDavid Nugent 333fe552114SDavid Nugent memset(got, 0, len+1); 334fe552114SDavid Nugent alarm(chat_alarm); 335fe552114SDavid Nugent alarmed = 0; 336fe552114SDavid Nugent 337fe552114SDavid Nugent while (r == 0 && i < len) { 338fe552114SDavid Nugent if (alarmed) 339fe552114SDavid Nugent r = 3; 340fe552114SDavid Nugent else { 341fe552114SDavid Nugent unsigned char ch; 342fe552114SDavid Nugent 343fe552114SDavid Nugent if (read(STDIN_FILENO, &ch, 1) == 1) { 344fe552114SDavid Nugent 345fe552114SDavid Nugent if (chat_debug & CHATDEBUG_RECEIVE) 346fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_recv '%s' m=%d", 347fe552114SDavid Nugent cleanchr(NULL, ch), i); 348fe552114SDavid Nugent 349fe552114SDavid Nugent if (ch == str[i]) 350fe552114SDavid Nugent got[i++] = ch; 351fe552114SDavid Nugent else if (i > 0) { 352fe552114SDavid Nugent int j = 1; 353fe552114SDavid Nugent 354fe552114SDavid Nugent /* See if we can resync on a 355fe552114SDavid Nugent * partial match in our buffer 356fe552114SDavid Nugent */ 3572dc8d58fSBruce Evans while (j < i && memcmp(got + j, str, i - j) != 0) 358fe552114SDavid Nugent j++; 359fe552114SDavid Nugent if (j < i) 360fe552114SDavid Nugent memcpy(got, got + j, i - j); 361fe552114SDavid Nugent i -= j; 362fe552114SDavid Nugent } 363fe552114SDavid Nugent } else 364fe552114SDavid Nugent r = alarmed ? 3 : 2; 365fe552114SDavid Nugent } 366fe552114SDavid Nugent } 367fe552114SDavid Nugent alarm(0); 368fe552114SDavid Nugent chat_unalarm(); 369fe552114SDavid Nugent alarmed = 0; 370fe552114SDavid Nugent free(got); 371fe552114SDavid Nugent } 372fe552114SDavid Nugent } 373fe552114SDavid Nugent 374fe552114SDavid Nugent if (chat_debug & CHATDEBUG_EXPECT) 375fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_expect %s", result(r)); 376fe552114SDavid Nugent 377fe552114SDavid Nugent return r; 378fe552114SDavid Nugent } 379fe552114SDavid Nugent 380fe552114SDavid Nugent 381fe552114SDavid Nugent /* 382fe552114SDavid Nugent * chat_send() 383fe552114SDavid Nugent * send a chat string 384fe552114SDavid Nugent */ 385fe552114SDavid Nugent 386fe552114SDavid Nugent static int 38795289b27SWarner Losh chat_send(char const *str) 388fe552114SDavid Nugent { 389fe552114SDavid Nugent int r = 0; 390fe552114SDavid Nugent 39150541c92SDimitry Andric if (chat_debug & CHATDEBUG_SEND) 392fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_send '%s'", cleanstr(str, strlen(str))); 393fe552114SDavid Nugent 394fe552114SDavid Nugent if (*str) { 395fe552114SDavid Nugent alarm(chat_alarm); 396fe552114SDavid Nugent alarmed = 0; 397fe552114SDavid Nugent while (r == 0 && *str) 398fe552114SDavid Nugent { 399fe552114SDavid Nugent unsigned char ch = (unsigned char)*str++; 400fe552114SDavid Nugent 401fe552114SDavid Nugent if (alarmed) 402fe552114SDavid Nugent r = 3; 403fe552114SDavid Nugent else if (ch == PAUSE_CH) 404fe552114SDavid Nugent usleep(500000); /* 1/2 second */ 405fe552114SDavid Nugent else { 406fe552114SDavid Nugent usleep(10000); /* be kind to modem */ 407fe552114SDavid Nugent if (write(STDOUT_FILENO, &ch, 1) != 1) 408fe552114SDavid Nugent r = alarmed ? 3 : 2; 409fe552114SDavid Nugent } 410fe552114SDavid Nugent } 411fe552114SDavid Nugent alarm(0); 412fe552114SDavid Nugent chat_unalarm(); 413fe552114SDavid Nugent alarmed = 0; 414fe552114SDavid Nugent } 415fe552114SDavid Nugent 416fe552114SDavid Nugent if (chat_debug & CHATDEBUG_SEND) 417fe552114SDavid Nugent syslog(LOG_DEBUG, "chat_send %s", result(r)); 418fe552114SDavid Nugent 419fe552114SDavid Nugent return r; 420fe552114SDavid Nugent } 421fe552114SDavid Nugent 422fe552114SDavid Nugent 423fe552114SDavid Nugent /* 424fe552114SDavid Nugent * getty_chat() 425fe552114SDavid Nugent * 426fe552114SDavid Nugent * Termination codes: 427fe552114SDavid Nugent * -1 - no script supplied 428fe552114SDavid Nugent * 0 - script terminated correctly 429fe552114SDavid Nugent * 1 - invalid argument, expect string too large, etc. 430fe552114SDavid Nugent * 2 - error on an I/O operation or fatal error condition 431fe552114SDavid Nugent * 3 - timeout waiting for a simple string 432fe552114SDavid Nugent * 433fe552114SDavid Nugent * Parameters: 434fe552114SDavid Nugent * char *scrstr - unparsed chat script 435fe552114SDavid Nugent * timeout - seconds timeout 436fe552114SDavid Nugent * debug - debug value (bitmask) 437fe552114SDavid Nugent */ 438fe552114SDavid Nugent 439fe552114SDavid Nugent int 44095289b27SWarner Losh getty_chat(char *scrstr, int timeout, int debug) 441fe552114SDavid Nugent { 442fe552114SDavid Nugent int r = -1; 443fe552114SDavid Nugent 444fe552114SDavid Nugent chat_alarm = timeout ? timeout : CHAT_DEFAULT_TIMEOUT; 445fe552114SDavid Nugent chat_debug = debug; 446fe552114SDavid Nugent 447fe552114SDavid Nugent if (scrstr != NULL) { 448fe552114SDavid Nugent char **script; 449fe552114SDavid Nugent 450fe552114SDavid Nugent if (chat_debug & CHATDEBUG_MISC) 451fe552114SDavid Nugent syslog(LOG_DEBUG, "getty_chat script='%s'", scrstr); 452fe552114SDavid Nugent 453fe552114SDavid Nugent if ((script = read_chat(&scrstr)) != NULL) { 454fe552114SDavid Nugent int i = r = 0; 455fe552114SDavid Nugent int off = 0; 456fe552114SDavid Nugent sig_t old_alarm; 457fe552114SDavid Nugent 45826015440SDavid Nugent /* 45926015440SDavid Nugent * We need to be in raw mode for all this 46026015440SDavid Nugent * Rely on caller... 461fe552114SDavid Nugent */ 462fe552114SDavid Nugent 463fe552114SDavid Nugent old_alarm = signal(SIGALRM, chat_alrm); 464fe552114SDavid Nugent chat_unalarm(); /* Force blocking mode at start */ 465fe552114SDavid Nugent 466fe552114SDavid Nugent /* 467fe552114SDavid Nugent * This is the send/expect loop 468fe552114SDavid Nugent */ 469fe552114SDavid Nugent while (r == 0 && script[i] != NULL) 470fe552114SDavid Nugent if ((r = chat_expect(script[i++])) == 0 && script[i] != NULL) 471fe552114SDavid Nugent r = chat_send(script[i++]); 472fe552114SDavid Nugent 473fe552114SDavid Nugent signal(SIGALRM, old_alarm); 474fe552114SDavid Nugent free(script); 475fe552114SDavid Nugent free(scrstr); 476fe552114SDavid Nugent 47726015440SDavid Nugent /* 47826015440SDavid Nugent * Ensure stdin is in blocking mode 479fe552114SDavid Nugent */ 480fe552114SDavid Nugent ioctl(STDIN_FILENO, FIONBIO, &off); 481fe552114SDavid Nugent } 482fe552114SDavid Nugent 483fe552114SDavid Nugent if (chat_debug & CHATDEBUG_MISC) 484fe552114SDavid Nugent syslog(LOG_DEBUG, "getty_chat %s", result(r)); 485fe552114SDavid Nugent 486fe552114SDavid Nugent } 487fe552114SDavid Nugent return r; 488fe552114SDavid Nugent } 489