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