diff options
author | cvs2svn <cvs2svn@FreeBSD.org> | 1997-03-27 03:07:27 +0000 |
---|---|---|
committer | cvs2svn <cvs2svn@FreeBSD.org> | 1997-03-27 03:07:27 +0000 |
commit | fe49c1266233ddc2306072aefb4e1c1d045060fe (patch) | |
tree | 134c187f06b248ff0eab3d486d5c69dbb2348647 /libexec | |
parent | 10891800ac4a1b9bcc24a79d523670a052935776 (diff) |
Notes
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/getty/chat.c | 515 |
1 files changed, 0 insertions, 515 deletions
diff --git a/libexec/getty/chat.c b/libexec/getty/chat.c deleted file mode 100644 index 24741950ae81a..0000000000000 --- a/libexec/getty/chat.c +++ /dev/null @@ -1,515 +0,0 @@ -/*- - * Copyright (c) 1997 - * David L Nugent <davidn@blaze.net.au>. - * All rights reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. This work was done expressly for inclusion into FreeBSD. Other use - * is permitted provided this notation is included. - * 4. Absolutely no warranty of function or purpose is made by the authors. - * 5. Modifications may be freely made to this file providing the above - * conditions are met. - * - * Modem chat module - send/expect style functions for getty - * For semi-intelligent modem handling. - * - * $Id$ - */ - -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/resource.h> -#include <sys/ttydefaults.h> -#include <sys/utsname.h> -#include <errno.h> -#include <signal.h> -#include <fcntl.h> -#include <time.h> -#include <ctype.h> -#include <fcntl.h> -#include <libutil.h> -#include <locale.h> -#include <setjmp.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <termios.h> -#include <time.h> -#include <unistd.h> -#include <sys/socket.h> - -#include "extern.h" - -#define PAUSE_CH (unsigned char)'\xff' /* pause kludge */ - -#define CHATDEBUG_RECEIVE 0x01 -#define CHATDEBUG_SEND 0x02 -#define CHATDEBUG_EXPECT 0x04 -#define CHATDEBUG_MISC 0x08 - -#define CHATDEBUG_DEFAULT 0 -#define CHAT_DEFAULT_TIMEOUT 10 - - -static int chat_debug = CHATDEBUG_DEFAULT; -static int chat_alarm = CHAT_DEFAULT_TIMEOUT; /* Default */ - -static volatile int alarmed = 0; - - -static void chat_alrm __P((int)); -static int chat_unalarm __P((void)); -static int getdigit __P((unsigned char **, int, int)); -static char **read_chat __P((char **)); -static char *cleanchr __P((char **, unsigned char)); -static char *cleanstr __P((const unsigned char *, int)); -static const char *result __P((int)); -static int chat_expect __P((const char *)); -static int chat_send __P((char const *)); - - -/* - * alarm signal handler - * handle timeouts in read/write - * change stdin to non-blocking mode to prevent - * possible hang in read(). - */ - -static void -chat_alrm(signo) - int signo; -{ - int on = 1; - - alarm(1); - alarmed = 1; - signal(SIGALRM, chat_alrm); - ioctl(STDIN_FILENO, FIONBIO, &on); -} - - -/* - * Turn back on blocking mode reset by chat_alrm() - */ - -static int -chat_unalarm() -{ - int off = 0; - return ioctl(STDIN_FILENO, FIONBIO, &off); -} - - -/* - * convert a string of a given base (octal/hex) to binary - */ - -static int -getdigit(ptr, base, max) - unsigned char **ptr; - int base, max; -{ - int i, val = 0; - char * q; - - static const char xdigits[] = "0123456789abcdef"; - - for (i = 0, q = *ptr; i++ < max; ++q) { - int sval; - const char * s = strchr(xdigits, tolower(*q)); - - if (s == NULL || (sval = s - xdigits) >= base) - break; - val = (val * base) + sval; - } - *ptr = q; - return val; -} - - -/* - * read_chat() - * Convert a whitespace delimtied string into an array - * of strings, being expect/send pairs - */ - -static char ** -read_chat(chatstr) - char **chatstr; -{ - char *str = *chatstr; - char **res = NULL; - - if (str != NULL) { - char *tmp = NULL; - int l; - - if ((l=strlen(str)) > 0 && (tmp=malloc(l + 1)) != NULL && - (res=malloc((l / 2 + 1) * sizeof(char *))) != NULL) { - static char ws[] = " \t"; - char * p; - - for (l = 0, p = strtok(strcpy(tmp, str), ws); - p != NULL; - p = strtok(NULL, ws)) - { - unsigned char *q, *r; - - /* Read escapes */ - for (q = r = (unsigned char *)p; *r; ++q) - { - int val; - - if (*q == '\\') - { - /* handle special escapes */ - switch (*++q) - { - case 'a': /* bell */ - *r++ = '\a'; - break; - case 'r': /* cr */ - *r++ = '\r'; - break; - case 'n': /* nl */ - *r++ = '\n'; - break; - case 'f': /* ff */ - *r++ = '\f'; - break; - case 'b': /* bs */ - *r++ = '\b'; - break; - case 'e': /* esc */ - *r++ = 27; - break; - case 't': /* tab */ - *r++ = '\t'; - break; - case 'p': /* pause */ - *r++ = PAUSE_CH; - break; - case 's': - case 'S': /* space */ - *r++ = ' '; - break; - case 'x': /* hexdigit */ - ++q; - *r++ = getdigit(&q, 16, 2); - --q; - break; - case '0': /* octal */ - ++q; - *r++ = getdigit(&q, 8, 3); - --q; - break; - default: /* literal */ - *r++ = *q; - break; - case 0: /* not past eos */ - --q; - break; - } - } else { - /* copy standard character */ - *r++ == *q; - } - } - - /* Remove surrounding quotes, if any - */ - if (*p == '"' || *p == '\'') { - q = strrchr(p+1, *p); - if (q != NULL && *q == *p && q[1] == '\0') { - *q = '\0'; - strcpy(p, p+1); - } - } - - res[l++] = p; - } - res[l] = NULL; - *chatstr = tmp; - return res; - } - free(tmp); - } - return res; -} - - -/* - * clean a character for display (ctrl/meta character) - */ - -static char * -cleanchr(buf, ch) - char **buf; - unsigned char ch; -{ - int l; - static char tmpbuf[5]; - char * tmp = buf ? *buf : tmpbuf; - - if (ch & 0x80) { - strcpy(tmp, "M-"); - l = 2; - ch &= 0x7f; - } else - l = 0; - - if (ch < 32) { - tmp[l++] = '^'; - tmp[l++] = ch + '@'; - } else if (ch == 127) { - tmp[l++] = '^'; - tmp[l++] = '?'; - } else - tmp[l++] = ch; - tmp[l] = '\0'; - - if (buf) - *buf = tmp + l; - return tmp; -} - - -/* - * clean a string for display (ctrl/meta characters) - */ - -static char * -cleanstr(s, l) - const unsigned char *s; - int l; -{ - static unsigned char * tmp = NULL; - static int tmplen = 0; - - if (tmplen < l * 4 + 1) - tmp = realloc(tmp, tmplen = l * 4 + 1); - - if (tmp == NULL) { - tmplen = 0; - return (char *)"(mem alloc error)"; - } else { - int i = 0; - char * p = tmp; - - while (i < l) - cleanchr(&p, s[i++]); - *p = '\0'; - } - - return tmp; -} - - -/* - * return result as an pseudo-english word - */ - -static const char * -result(r) - int r; -{ - static const char * results[] = { - "OK", "MEMERROR", "IOERROR", "TIMEOUT" - }; - return results[r & 3]; -} - - -/* - * chat_expect() - * scan input for an expected string - */ - -static int -chat_expect(str) - const char *str; -{ - int len, r = 0; - - if (chat_debug & CHATDEBUG_EXPECT) - syslog(LOG_DEBUG, "chat_expect '%s'", cleanstr(str, strlen(str))); - - if ((len = strlen(str)) > 0) { - int i = 0; - char * got; - - if ((got = malloc(len + 1)) == NULL) - r = 1; - else { - - memset(got, 0, len+1); - alarm(chat_alarm); - alarmed = 0; - - while (r == 0 && i < len) { - if (alarmed) - r = 3; - else { - unsigned char ch; - - if (read(STDIN_FILENO, &ch, 1) == 1) { - - if (chat_debug & CHATDEBUG_RECEIVE) - syslog(LOG_DEBUG, "chat_recv '%s' m=%d", - cleanchr(NULL, ch), i); - - if (ch == str[i]) - got[i++] = ch; - else if (i > 0) { - int j = 1; - - /* See if we can resync on a - * partial match in our buffer - */ - while (j < i && memcmp(got + j, str, i - j) != NULL) - j++; - if (j < i) - memcpy(got, got + j, i - j); - i -= j; - } - } else - r = alarmed ? 3 : 2; - } - } - alarm(0); - chat_unalarm(); - alarmed = 0; - free(got); - } - } - - if (chat_debug & CHATDEBUG_EXPECT) - syslog(LOG_DEBUG, "chat_expect %s", result(r)); - - return r; -} - - -/* - * chat_send() - * send a chat string - */ - -static int -chat_send(str) - char const *str; -{ - int r = 0; - - if (chat_debug && CHATDEBUG_SEND) - syslog(LOG_DEBUG, "chat_send '%s'", cleanstr(str, strlen(str))); - - if (*str) { - alarm(chat_alarm); - alarmed = 0; - while (r == 0 && *str) - { - unsigned char ch = (unsigned char)*str++; - - if (alarmed) - r = 3; - else if (ch == PAUSE_CH) - usleep(500000); /* 1/2 second */ - else { - usleep(10000); /* be kind to modem */ - if (write(STDOUT_FILENO, &ch, 1) != 1) - r = alarmed ? 3 : 2; - } - } - alarm(0); - chat_unalarm(); - alarmed = 0; - } - - if (chat_debug & CHATDEBUG_SEND) - syslog(LOG_DEBUG, "chat_send %s", result(r)); - - return r; -} - - -/* - * getty_chat() - * - * Termination codes: - * -1 - no script supplied - * 0 - script terminated correctly - * 1 - invalid argument, expect string too large, etc. - * 2 - error on an I/O operation or fatal error condition - * 3 - timeout waiting for a simple string - * - * Parameters: - * char *scrstr - unparsed chat script - * timeout - seconds timeout - * debug - debug value (bitmask) - */ - -int -getty_chat(scrstr, timeout, debug) - char *scrstr; - int timeout, debug; -{ - int r = -1; - - chat_alarm = timeout ? timeout : CHAT_DEFAULT_TIMEOUT; - chat_debug = debug; - - if (scrstr != NULL) { - char **script; - - if (chat_debug & CHATDEBUG_MISC) - syslog(LOG_DEBUG, "getty_chat script='%s'", scrstr); - - if ((script = read_chat(&scrstr)) != NULL) { - int i = r = 0; - int off = 0; - sig_t old_alarm; - struct termios tneed; - - /* - * We need to be in raw mode for all this - * Rely on caller... - */ - - old_alarm = signal(SIGALRM, chat_alrm); - chat_unalarm(); /* Force blocking mode at start */ - - /* - * This is the send/expect loop - */ - while (r == 0 && script[i] != NULL) - if ((r = chat_expect(script[i++])) == 0 && script[i] != NULL) - r = chat_send(script[i++]); - - signal(SIGALRM, old_alarm); - free(script); - free(scrstr); - - /* - * Ensure stdin is in blocking mode - */ - ioctl(STDIN_FILENO, FIONBIO, &off); - } - - if (chat_debug & CHATDEBUG_MISC) - syslog(LOG_DEBUG, "getty_chat %s", result(r)); - - } - return r; -} |