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