X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=chat%2Fchat.c;h=47248fa65c3d2897c293c2079f227a42a7152ac8;hb=86dd2eec100dbdfc31c379c0e380cc439fc0921b;hp=5ce1336e381329afb811bb71e209efd840ade535;hpb=084ed8efcf30963586ac5823711f9e040b8e70ce;p=ppp.git diff --git a/chat/chat.c b/chat/chat.c index 5ce1336..47248fa 100644 --- a/chat/chat.c +++ b/chat/chat.c @@ -14,6 +14,12 @@ * This software is in the public domain. * * ----------------- + * 22-May-99 added environment substitutuion, enabled with -E switch. + * Andreas Arens . + * + * 12-May-99 added a feature to read data to be sent from a file, + * if the send string starts with @. Idea from gpk . + * * added -T and -U option and \T and \U substitution to pass a phone * number into chat script. Two are needed for some ISDN TA applications. * Keith Dart @@ -74,11 +80,14 @@ * Columbus, OH 43221 * (614)451-1883 * - * */ +#ifndef __STDC__ +#define const +#endif + #ifndef lint -static char rcsid[] = "$Id: chat.c,v 1.20 1999/03/31 12:28:16 paulus Exp $"; +static const char rcsid[] = "$Id: chat.c,v 1.29 2003/03/04 06:17:21 fcusack Exp $"; #endif #include @@ -163,6 +172,7 @@ int to_stderr = 0; int Verbose = 0; int quiet = 0; int report = 0; +int use_env = 0; int exit_code = 0; FILE* report_fp = (FILE *) 0; char *report_file = (char *) 0; @@ -193,7 +203,7 @@ int n_aborts = 0, abort_next = 0, timeout_next = 0, echo_next = 0; int clear_abort_next = 0; char *report_string[MAX_REPORTS] ; -char report_buffer[50] ; +char report_buffer[256] ; int n_reports = 0, report_next = 0, report_gathering = 0 ; int clear_report_next = 0; @@ -201,6 +211,7 @@ int say_next = 0, hup_next = 0; void *dup_mem __P((void *b, size_t c)); void *copy_of __P((char *s)); +char *grow __P((char *s, char **p, size_t len)); void usage __P((void)); void logf __P((const char *fmt, ...)); void fatal __P((int code, const char *fmt, ...)); @@ -250,8 +261,23 @@ char *s; return dup_mem (s, strlen (s) + 1); } +/* grow a char buffer and keep a pointer offset */ +char *grow(s, p, len) +char *s; +char **p; +size_t len; +{ + size_t l = *p - s; /* save p as distance into s */ + + s = realloc(s, len); + if (!s) + fatal(2, "memory error!"); + *p = s + l; /* restore p */ + return s; +} + /* - * chat [ -v ] [-T number] [-U number] [ -t timeout ] [ -f chat-file ] \ + * chat [ -v ] [ -E ] [ -T number ] [ -U number ] [ -t timeout ] [ -f chat-file ] \ * [ -r report-file ] \ * [...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]] * @@ -274,6 +300,10 @@ main(argc, argv) ++echo; break; + case 'E': + ++use_env; + break; + case 'v': ++verbose; break; @@ -455,8 +485,8 @@ char *chat_file; void usage() { fprintf(stderr, "\ -Usage: %s [-e] [-v] [-t timeout] [-r report-file] [-T phone-number]\n\ - [-U phone-number2] {-f chat-file | chat-script}\n", program_name); +Usage: %s [-e] [-E] [-v] [-V] [-t timeout] [-r report-file]\n\ + [-T phone-number] [-U phone-number2] {-f chat-file | chat-script}\n", program_name); exit(1); } @@ -612,26 +642,26 @@ int status; exit(status); terminating = 1; echo_stderr(-1); - if (report_file != (char *) 0 && report_fp != (FILE *) NULL) { /* * Allow the last of the report string to be gathered before we terminate. */ - if (report_gathering) { - int c, rep_len; + if (report_gathering) { + int c, rep_len; - rep_len = strlen(report_buffer); - while (rep_len + 1 <= sizeof(report_buffer)) { - alarm(1); - c = get_char(); - alarm(0); - if (c < 0 || iscntrl(c)) - break; - report_buffer[rep_len] = c; - ++rep_len; - } - report_buffer[rep_len] = 0; - fprintf (report_fp, "chat: %s\n", report_buffer); + rep_len = strlen(report_buffer); + while (rep_len + 1 <= sizeof(report_buffer)) { + alarm(1); + c = get_char(); + alarm(0); + if (c < 0 || iscntrl(c)) + break; + report_buffer[rep_len] = c; + ++rep_len; } + report_buffer[rep_len] = 0; + fprintf (report_fp, "chat: %s\n", report_buffer); + } + if (report_file != (char *) 0 && report_fp != (FILE *) NULL) { if (verbose) fprintf (report_fp, "Closing \"%s\".\n", report_file); fclose (report_fp); @@ -655,51 +685,78 @@ char *clean(s, sending) register char *s; int sending; /* set to 1 when sending (putting) this string. */ { - char temp[STR_LEN], cur_chr; - register char *s1, *phchar; + char cur_chr; + char *s1, *p, *phchar; int add_return = sending; -#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7')) + size_t len = strlen(s) + 3; /* see len comments below */ + +#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7')) +#define isalnumx(chr) ((((chr) >= '0') && ((chr) <= '9')) \ + || (((chr) >= 'a') && ((chr) <= 'z')) \ + || (((chr) >= 'A') && ((chr) <= 'Z')) \ + || (chr) == '_') - s1 = temp; + p = s1 = malloc(len); + if (!p) + fatal(2, "memory error!"); while (*s) { cur_chr = *s++; if (cur_chr == '^') { cur_chr = *s++; if (cur_chr == '\0') { - *s1++ = '^'; + *p++ = '^'; break; } cur_chr &= 0x1F; if (cur_chr != 0) { - *s1++ = cur_chr; + *p++ = cur_chr; + } + continue; + } + + if (use_env && cur_chr == '$') { /* ARI */ + char c; + + phchar = s; + while (isalnumx(*s)) + s++; + c = *s; /* save */ + *s = '\0'; + phchar = getenv(phchar); + *s = c; /* restore */ + if (phchar) { + len += strlen(phchar); + s1 = grow(s1, &p, len); + while (*phchar) + *p++ = *phchar++; } continue; } if (cur_chr != '\\') { - *s1++ = cur_chr; + *p++ = cur_chr; continue; } cur_chr = *s++; if (cur_chr == '\0') { if (sending) { - *s1++ = '\\'; - *s1++ = '\\'; + *p++ = '\\'; + *p++ = '\\'; /* +1 for len */ } break; } switch (cur_chr) { case 'b': - *s1++ = '\b'; + *p++ = '\b'; break; case 'c': if (sending && *s == '\0') add_return = 0; else - *s1++ = cur_chr; + *p++ = cur_chr; break; case '\\': @@ -707,30 +764,33 @@ int sending; /* set to 1 when sending (putting) this string. */ case 'p': case 'd': if (sending) - *s1++ = '\\'; - - *s1++ = cur_chr; + *p++ = '\\'; + *p++ = cur_chr; break; case 'T': if (sending && phone_num) { - for ( phchar = phone_num; *phchar != '\0'; phchar++) - *s1++ = *phchar; + len += strlen(phone_num); + s1 = grow(s1, &p, len); + for (phchar = phone_num; *phchar != '\0'; phchar++) + *p++ = *phchar; } else { - *s1++ = '\\'; - *s1++ = 'T'; + *p++ = '\\'; + *p++ = 'T'; } break; case 'U': if (sending && phone_num2) { - for ( phchar = phone_num2; *phchar != '\0'; phchar++) - *s1++ = *phchar; + len += strlen(phone_num2); + s1 = grow(s1, &p, len); + for (phchar = phone_num2; *phchar != '\0'; phchar++) + *p++ = *phchar; } else { - *s1++ = '\\'; - *s1++ = 'U'; + *p++ = '\\'; + *p++ = 'U'; } break; @@ -739,30 +799,37 @@ int sending; /* set to 1 when sending (putting) this string. */ break; case 'r': - *s1++ = '\r'; + *p++ = '\r'; break; case 'n': - *s1++ = '\n'; + *p++ = '\n'; break; case 's': - *s1++ = ' '; + *p++ = ' '; break; case 't': - *s1++ = '\t'; + *p++ = '\t'; break; case 'N': if (sending) { - *s1++ = '\\'; - *s1++ = '\0'; + *p++ = '\\'; + *p++ = '\0'; } else - *s1++ = 'N'; + *p++ = 'N'; break; - + + case '$': /* ARI */ + if (use_env) { + *p++ = cur_chr; + break; + } + /* FALL THROUGH */ + default: if (isoctal (cur_chr)) { cur_chr &= 0x07; @@ -777,25 +844,24 @@ int sending; /* set to 1 when sending (putting) this string. */ if (cur_chr != 0 || sending) { if (sending && (cur_chr == '\\' || cur_chr == 0)) - *s1++ = '\\'; - *s1++ = cur_chr; + *p++ = '\\'; + *p++ = cur_chr; } break; } if (sending) - *s1++ = '\\'; - *s1++ = cur_chr; + *p++ = '\\'; + *p++ = cur_chr; break; } } if (add_return) - *s1++ = '\r'; + *p++ = '\r'; /* +2 for len */ - *s1++ = '\0'; /* guarantee closure */ - *s1++ = '\0'; /* terminate the string */ - return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */ + *p = '\0'; /* +3 for len */ + return s1; } /* @@ -971,9 +1037,11 @@ int c; void chat_send (s) register char *s; { + char file_data[STR_LEN]; + if (say_next) { say_next = 0; - s = clean(s,0); + s = clean(s, 1); write(2, s, strlen(s)); free(s); return; @@ -1054,8 +1122,8 @@ register char *s; fatal(2, "Too many REPORT strings"); s1 = clean(s, 0); - - if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1) + if (strlen(s1) > strlen(s) + || strlen(s1) + 1 > sizeof(fail_buffer)) fatal(1, "Illegal or too-long REPORT string ('%v')", s); report_string[n_reports++] = s1; @@ -1075,7 +1143,8 @@ register char *s; s1 = clean(s, 0); - if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1) + if (strlen(s1) > strlen(s) + || strlen(s1) + 1 > sizeof(fail_buffer)) fatal(1, "Illegal or too-long REPORT string ('%v')", s); old_max = n_reports; @@ -1109,6 +1178,43 @@ register char *s; return; } + /* + * The syntax @filename means read the string to send from the + * file `filename'. + */ + if (s[0] == '@') { + /* skip the @ and any following white-space */ + char *fn = s; + while (*++fn == ' ' || *fn == '\t') + ; + + if (*fn != 0) { + FILE *f; + int n = 0; + + /* open the file and read until STR_LEN-1 bytes or end-of-file */ + f = fopen(fn, "r"); + if (f == NULL) + fatal(1, "%s -- open failed: %m", fn); + while (n < STR_LEN - 1) { + int nr = fread(&file_data[n], 1, STR_LEN - 1 - n, f); + if (nr < 0) + fatal(1, "%s -- read error", fn); + if (nr == 0) + break; + n += nr; + } + fclose(f); + + /* use the string we got as the string to send, + but trim off the final newline if any. */ + if (n > 0 && file_data[n-1] == '\n') + --n; + file_data[n] = 0; + s = file_data; + } + } + if (strcmp(s, "EOT") == 0) s = "^D\\c"; else if (strcmp(s, "BREAK") == 0) @@ -1392,7 +1498,8 @@ register char *string; if (s >= end) { if (logged < s - minlen) { - logf("%0.*v", s - logged, logged); + if (verbose) + logf("%0.*v", s - logged, logged); logged = s; } s -= minlen;