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