xref: /freebsd/usr.bin/chat/chat.c (revision 9f65f104f5d16e582ddbf8ccdfa81b324d5d4561)
19b1aec48SLars Fredriksen /*
29b1aec48SLars Fredriksen  *	Chat -- a program for automatic session establishment (i.e. dial
39b1aec48SLars Fredriksen  *		the phone and log in).
49b1aec48SLars Fredriksen  *
59f65f104SPeter Wemm  * Standard termination codes:
69f65f104SPeter Wemm  *  0 - successful completion of the script
79f65f104SPeter Wemm  *  1 - invalid argument, expect string too large, etc.
89f65f104SPeter Wemm  *  2 - error on an I/O operation or fatal error condtion.
99f65f104SPeter Wemm  *  3 - timeout waiting for a simple string.
109f65f104SPeter Wemm  *  4 - the first string declared as "ABORT"
119f65f104SPeter Wemm  *  5 - the second string declared as "ABORT"
129f65f104SPeter Wemm  *  6 - ... and so on for successive ABORT strings.
139f65f104SPeter Wemm  *
149b1aec48SLars Fredriksen  *	This software is in the public domain.
159b1aec48SLars Fredriksen  *
169b1aec48SLars Fredriksen  *	Please send all bug reports, requests for information, etc. to:
179b1aec48SLars Fredriksen  *
189b1aec48SLars Fredriksen  *		Al Longyear (longyear@netcom.com)
199b1aec48SLars Fredriksen  *		(I was the last person to change this code.)
209b1aec48SLars Fredriksen  *
219f65f104SPeter Wemm  *      Added -r "report file" switch & REPORT keyword.
229f65f104SPeter Wemm  *              Robert Geer <bgeer@xmission.com>
239f65f104SPeter Wemm  *
249b1aec48SLars Fredriksen  *	The original author is:
259b1aec48SLars Fredriksen  *
269b1aec48SLars Fredriksen  *		Karl Fox <karl@MorningStar.Com>
279b1aec48SLars Fredriksen  *		Morning Star Technologies, Inc.
289b1aec48SLars Fredriksen  *		1760 Zollinger Road
299b1aec48SLars Fredriksen  *		Columbus, OH  43221
309b1aec48SLars Fredriksen  *		(614)451-1883
319f65f104SPeter Wemm  *
329b1aec48SLars Fredriksen  */
339b1aec48SLars Fredriksen 
349f65f104SPeter Wemm static char rcsid[] = "$Id: chat.c,v 1.1.1.1 1994/11/12 05:25:32 lars Exp $";
359b1aec48SLars Fredriksen 
369b1aec48SLars Fredriksen #include <stdio.h>
379f65f104SPeter Wemm #include <time.h>
389b1aec48SLars Fredriksen #include <fcntl.h>
399b1aec48SLars Fredriksen #include <signal.h>
409b1aec48SLars Fredriksen #include <errno.h>
419b1aec48SLars Fredriksen #include <string.h>
429b1aec48SLars Fredriksen #include <stdlib.h>
439b1aec48SLars Fredriksen #include <sys/types.h>
449b1aec48SLars Fredriksen #include <sys/stat.h>
459b1aec48SLars Fredriksen #include <syslog.h>
469b1aec48SLars Fredriksen 
479b1aec48SLars Fredriksen #ifndef TERMIO
489b1aec48SLars Fredriksen #undef	TERMIOS
499b1aec48SLars Fredriksen #define TERMIOS
509b1aec48SLars Fredriksen #endif
519b1aec48SLars Fredriksen 
529b1aec48SLars Fredriksen #ifdef TERMIO
539b1aec48SLars Fredriksen #include <termio.h>
549b1aec48SLars Fredriksen #endif
559b1aec48SLars Fredriksen #ifdef TERMIOS
569b1aec48SLars Fredriksen #include <termios.h>
579b1aec48SLars Fredriksen #endif
589b1aec48SLars Fredriksen 
599b1aec48SLars Fredriksen #define	STR_LEN	1024
609b1aec48SLars Fredriksen 
619b1aec48SLars Fredriksen #ifndef SIGTYPE
629b1aec48SLars Fredriksen #define SIGTYPE void
639b1aec48SLars Fredriksen #endif
649b1aec48SLars Fredriksen 
659b1aec48SLars Fredriksen #ifdef __STDC__
669b1aec48SLars Fredriksen #undef __P
679b1aec48SLars Fredriksen #define __P(x)	x
689b1aec48SLars Fredriksen #else
699b1aec48SLars Fredriksen #define __P(x)	()
709b1aec48SLars Fredriksen #define const
719b1aec48SLars Fredriksen #endif
729b1aec48SLars Fredriksen 
739f65f104SPeter Wemm #ifndef O_NONBLOCK
749f65f104SPeter Wemm #define O_NONBLOCK	O_NDELAY
759f65f104SPeter Wemm #endif
769f65f104SPeter Wemm 
779b1aec48SLars Fredriksen /*************** Micro getopt() *********************************************/
789b1aec48SLars Fredriksen #define	OPTION(c,v)	(_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \
799b1aec48SLars Fredriksen 				(--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\
809b1aec48SLars Fredriksen 				&&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0))
819b1aec48SLars Fredriksen #define	OPTARG(c,v)	(_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \
829b1aec48SLars Fredriksen 				(_O=4,(char*)0):(char*)0)
839b1aec48SLars Fredriksen #define	OPTONLYARG(c,v)	(_O&2&&**v?(_O=1,--c,*v++):(char*)0)
849b1aec48SLars Fredriksen #define	ARG(c,v)	(c?(--c,*v++):(char*)0)
859b1aec48SLars Fredriksen 
869b1aec48SLars Fredriksen static int _O = 0;		/* Internal state */
879b1aec48SLars Fredriksen /*************** Micro getopt() *********************************************/
889b1aec48SLars Fredriksen 
899b1aec48SLars Fredriksen char *program_name;
909b1aec48SLars Fredriksen 
919b1aec48SLars Fredriksen #define	MAX_ABORTS		50
929f65f104SPeter Wemm #define	MAX_REPORTS		50
939b1aec48SLars Fredriksen #define	DEFAULT_CHAT_TIMEOUT	45
949b1aec48SLars Fredriksen 
959b1aec48SLars Fredriksen int verbose       = 0;
969b1aec48SLars Fredriksen int quiet         = 0;
979f65f104SPeter Wemm int report        = 0;
989f65f104SPeter Wemm int exit_code     = 0;
999f65f104SPeter Wemm FILE* report_fp   = (FILE *) 0;
1009f65f104SPeter Wemm char *report_file = (char *) 0;
1019b1aec48SLars Fredriksen char *chat_file   = (char *) 0;
1029b1aec48SLars Fredriksen int timeout       = DEFAULT_CHAT_TIMEOUT;
1039b1aec48SLars Fredriksen 
1049b1aec48SLars Fredriksen int have_tty_parameters = 0;
1059f65f104SPeter Wemm 
1069b1aec48SLars Fredriksen #ifdef TERMIO
1079f65f104SPeter Wemm #define term_parms struct termio
1089f65f104SPeter Wemm #define get_term_param(param) ioctl(0, TCGETA, param)
1099f65f104SPeter Wemm #define set_term_param(param) ioctl(0, TCSETA, param)
1109b1aec48SLars Fredriksen struct termio saved_tty_parameters;
1119b1aec48SLars Fredriksen #endif
1129f65f104SPeter Wemm 
1139b1aec48SLars Fredriksen #ifdef TERMIOS
1149f65f104SPeter Wemm #define term_parms struct termios
1159f65f104SPeter Wemm #define get_term_param(param) tcgetattr(0, param)
1169f65f104SPeter Wemm #define set_term_param(param) tcsetattr(0, TCSANOW, param)
1179b1aec48SLars Fredriksen struct termios saved_tty_parameters;
1189b1aec48SLars Fredriksen #endif
1199b1aec48SLars Fredriksen 
1209b1aec48SLars Fredriksen char *abort_string[MAX_ABORTS], *fail_reason = (char *)0,
1219b1aec48SLars Fredriksen 	fail_buffer[50];
1229b1aec48SLars Fredriksen int n_aborts = 0, abort_next = 0, timeout_next = 0;
1239b1aec48SLars Fredriksen 
1249f65f104SPeter Wemm char *report_string[MAX_REPORTS] ;
1259f65f104SPeter Wemm char  report_buffer[50] ;
1269f65f104SPeter Wemm int n_reports = 0, report_next = 0, report_gathering = 0 ;
1279f65f104SPeter Wemm 
1289b1aec48SLars Fredriksen void *dup_mem __P((void *b, size_t c));
1299b1aec48SLars Fredriksen void *copy_of __P((char *s));
1309b1aec48SLars Fredriksen void usage __P((void));
1319b1aec48SLars Fredriksen void logf __P((const char *str));
1329b1aec48SLars Fredriksen void logflush __P((void));
1339b1aec48SLars Fredriksen void fatal __P((const char *msg));
1349b1aec48SLars Fredriksen void sysfatal __P((const char *msg));
1359b1aec48SLars Fredriksen SIGTYPE sigalrm __P((int signo));
1369b1aec48SLars Fredriksen SIGTYPE sigint __P((int signo));
1379b1aec48SLars Fredriksen SIGTYPE sigterm __P((int signo));
1389b1aec48SLars Fredriksen SIGTYPE sighup __P((int signo));
1399b1aec48SLars Fredriksen void unalarm __P((void));
1409b1aec48SLars Fredriksen void init __P((void));
1419b1aec48SLars Fredriksen void set_tty_parameters __P((void));
1429b1aec48SLars Fredriksen void break_sequence __P((void));
1439b1aec48SLars Fredriksen void terminate __P((int status));
1449b1aec48SLars Fredriksen void do_file __P((char *chat_file));
1459b1aec48SLars Fredriksen int  get_string __P((register char *string));
1469b1aec48SLars Fredriksen int  put_string __P((register char *s));
1479b1aec48SLars Fredriksen int  write_char __P((int c));
1489f65f104SPeter Wemm int  put_char __P((int c));
1499b1aec48SLars Fredriksen int  get_char __P((void));
1509b1aec48SLars Fredriksen void chat_send __P((register char *s));
1519f65f104SPeter Wemm char *character __P((int c));
1529b1aec48SLars Fredriksen void chat_expect __P((register char *s));
1539b1aec48SLars Fredriksen char *clean __P((register char *s, int sending));
1549b1aec48SLars Fredriksen void break_sequence __P((void));
1559b1aec48SLars Fredriksen void terminate __P((int status));
1569b1aec48SLars Fredriksen void die __P((void));
1579b1aec48SLars Fredriksen 
1589b1aec48SLars Fredriksen void *dup_mem(b, c)
1599b1aec48SLars Fredriksen void *b;
1609b1aec48SLars Fredriksen size_t c;
1619b1aec48SLars Fredriksen     {
1629b1aec48SLars Fredriksen     void *ans = malloc (c);
1639b1aec48SLars Fredriksen     if (!ans)
1649f65f104SPeter Wemm         {
1659b1aec48SLars Fredriksen 	fatal ("memory error!\n");
1669f65f104SPeter Wemm         }
1679b1aec48SLars Fredriksen     memcpy (ans, b, c);
1689b1aec48SLars Fredriksen     return ans;
1699b1aec48SLars Fredriksen     }
1709b1aec48SLars Fredriksen 
1719b1aec48SLars Fredriksen void *copy_of (s)
1729b1aec48SLars Fredriksen char *s;
1739b1aec48SLars Fredriksen     {
1749b1aec48SLars Fredriksen     return dup_mem (s, strlen (s) + 1);
1759b1aec48SLars Fredriksen     }
1769b1aec48SLars Fredriksen 
1779b1aec48SLars Fredriksen /*
1789f65f104SPeter Wemm  *	chat [ -v ] [ -t timeout ] [ -f chat-file ] [ -r report-file ] \
1799b1aec48SLars Fredriksen  *		[...[[expect[-say[-expect...]] say expect[-say[-expect]] ...]]]
1809b1aec48SLars Fredriksen  *
1819b1aec48SLars Fredriksen  *	Perform a UUCP-dialer-like chat script on stdin and stdout.
1829b1aec48SLars Fredriksen  */
1839b1aec48SLars Fredriksen int
1849b1aec48SLars Fredriksen main(argc, argv)
1859b1aec48SLars Fredriksen int argc;
1869b1aec48SLars Fredriksen char **argv;
1879b1aec48SLars Fredriksen     {
1889b1aec48SLars Fredriksen     int option;
1899b1aec48SLars Fredriksen     char *arg;
1909b1aec48SLars Fredriksen 
1919b1aec48SLars Fredriksen     program_name = *argv;
1929f65f104SPeter Wemm     tzset();
1939b1aec48SLars Fredriksen 
1949b1aec48SLars Fredriksen     while (option = OPTION(argc, argv))
1959f65f104SPeter Wemm         {
1969b1aec48SLars Fredriksen 	switch (option)
1979b1aec48SLars Fredriksen 	    {
1989b1aec48SLars Fredriksen 	    case 'v':
1999b1aec48SLars Fredriksen 		++verbose;
2009b1aec48SLars Fredriksen 		break;
2019b1aec48SLars Fredriksen 
2029b1aec48SLars Fredriksen 	    case 'f':
2039b1aec48SLars Fredriksen 		if (arg = OPTARG(argc, argv))
2049f65f104SPeter Wemm 		    {
2059b1aec48SLars Fredriksen 		    chat_file = copy_of(arg);
2069f65f104SPeter Wemm 		    }
2079b1aec48SLars Fredriksen 		else
2089f65f104SPeter Wemm 		    {
2099b1aec48SLars Fredriksen 		    usage();
2109f65f104SPeter Wemm 		    }
2119b1aec48SLars Fredriksen 		break;
2129b1aec48SLars Fredriksen 
2139b1aec48SLars Fredriksen 	    case 't':
2149b1aec48SLars Fredriksen 		if (arg = OPTARG(argc, argv))
2159f65f104SPeter Wemm 		    {
2169b1aec48SLars Fredriksen 		    timeout = atoi(arg);
2179f65f104SPeter Wemm 		    }
2189b1aec48SLars Fredriksen 		else
2199f65f104SPeter Wemm 		    {
2209b1aec48SLars Fredriksen 		    usage();
2219f65f104SPeter Wemm 		    }
2229f65f104SPeter Wemm 		break;
2239b1aec48SLars Fredriksen 
2249f65f104SPeter Wemm 	    case 'r':
2259f65f104SPeter Wemm 		arg = OPTARG (argc, argv);
2269f65f104SPeter Wemm 		if (arg)
2279f65f104SPeter Wemm 		    {
2289f65f104SPeter Wemm 		    if (report_fp != NULL)
2299f65f104SPeter Wemm 		        {
2309f65f104SPeter Wemm 			fclose (report_fp);
2319f65f104SPeter Wemm 		        }
2329f65f104SPeter Wemm 		    report_file = copy_of (arg);
2339f65f104SPeter Wemm 		    report_fp   = fopen (report_file, "a");
2349f65f104SPeter Wemm 		    if (report_fp != NULL)
2359f65f104SPeter Wemm 		        {
2369f65f104SPeter Wemm 			if (verbose)
2379f65f104SPeter Wemm 			    {
2389f65f104SPeter Wemm 			    fprintf (report_fp, "Opening \"%s\"...\n",
2399f65f104SPeter Wemm 				     report_file);
2409f65f104SPeter Wemm 			    }
2419f65f104SPeter Wemm 			report = 1;
2429f65f104SPeter Wemm 		        }
2439f65f104SPeter Wemm 		    }
2449b1aec48SLars Fredriksen 		break;
2459b1aec48SLars Fredriksen 
2469b1aec48SLars Fredriksen 	    default:
2479b1aec48SLars Fredriksen 		usage();
2489f65f104SPeter Wemm 		break;
2499f65f104SPeter Wemm 	    }
2509f65f104SPeter Wemm       }
2519f65f104SPeter Wemm /*
2529f65f104SPeter Wemm  * Default the report file to the stderr location
2539f65f104SPeter Wemm  */
2549f65f104SPeter Wemm     if (report_fp == NULL)
2559f65f104SPeter Wemm         {
2569f65f104SPeter Wemm 	report_fp = stderr;
2579b1aec48SLars Fredriksen         }
2589b1aec48SLars Fredriksen 
2599b1aec48SLars Fredriksen #ifdef ultrix
2609b1aec48SLars Fredriksen     openlog("chat", LOG_PID);
2619b1aec48SLars Fredriksen #else
2629b1aec48SLars Fredriksen     openlog("chat", LOG_PID | LOG_NDELAY, LOG_LOCAL2);
2639b1aec48SLars Fredriksen 
2649f65f104SPeter Wemm     if (verbose)
2659f65f104SPeter Wemm         {
2669b1aec48SLars Fredriksen 	setlogmask(LOG_UPTO(LOG_INFO));
2679f65f104SPeter Wemm         }
2689f65f104SPeter Wemm     else
2699f65f104SPeter Wemm         {
2709b1aec48SLars Fredriksen 	setlogmask(LOG_UPTO(LOG_WARNING));
2719b1aec48SLars Fredriksen         }
2729b1aec48SLars Fredriksen #endif
2739b1aec48SLars Fredriksen 
2749b1aec48SLars Fredriksen     init();
2759b1aec48SLars Fredriksen 
2769b1aec48SLars Fredriksen     if (chat_file != NULL)
2779b1aec48SLars Fredriksen 	{
2789b1aec48SLars Fredriksen 	arg = ARG(argc, argv);
2799b1aec48SLars Fredriksen 	if (arg != NULL)
2809f65f104SPeter Wemm 	    {
2819b1aec48SLars Fredriksen 	    usage();
2829f65f104SPeter Wemm 	    }
2839b1aec48SLars Fredriksen 	else
2849f65f104SPeter Wemm 	    {
2859b1aec48SLars Fredriksen 	    do_file (chat_file);
2869b1aec48SLars Fredriksen 	    }
2879f65f104SPeter Wemm 	}
2889b1aec48SLars Fredriksen     else
2899b1aec48SLars Fredriksen 	{
2909b1aec48SLars Fredriksen 	while (arg = ARG(argc, argv))
2919b1aec48SLars Fredriksen 	    {
2929b1aec48SLars Fredriksen 	    chat_expect(arg);
2939b1aec48SLars Fredriksen 
2949b1aec48SLars Fredriksen 	    if (arg = ARG(argc, argv))
2959f65f104SPeter Wemm 	        {
2969b1aec48SLars Fredriksen 		chat_send(arg);
2979b1aec48SLars Fredriksen 	        }
2989b1aec48SLars Fredriksen 	    }
2999f65f104SPeter Wemm 	}
3009b1aec48SLars Fredriksen 
3019b1aec48SLars Fredriksen     terminate(0);
3029b1aec48SLars Fredriksen     }
3039b1aec48SLars Fredriksen 
3049b1aec48SLars Fredriksen /*
3059b1aec48SLars Fredriksen  *  Process a chat script when read from a file.
3069b1aec48SLars Fredriksen  */
3079b1aec48SLars Fredriksen 
3089b1aec48SLars Fredriksen void do_file (chat_file)
3099b1aec48SLars Fredriksen char *chat_file;
3109b1aec48SLars Fredriksen     {
3119b1aec48SLars Fredriksen     int linect, len, sendflg;
3129b1aec48SLars Fredriksen     char *sp, *arg, quote;
3139b1aec48SLars Fredriksen     char buf [STR_LEN];
3149b1aec48SLars Fredriksen     FILE *cfp;
3159b1aec48SLars Fredriksen 
3169f65f104SPeter Wemm     cfp = fopen (chat_file, "r");
3179f65f104SPeter Wemm     if (cfp == NULL)
3189b1aec48SLars Fredriksen 	{
3199b1aec48SLars Fredriksen 	syslog (LOG_ERR, "%s -- open failed: %m", chat_file);
3209b1aec48SLars Fredriksen 	terminate (1);
3219b1aec48SLars Fredriksen 	}
3229b1aec48SLars Fredriksen 
3239b1aec48SLars Fredriksen     linect = 0;
3249b1aec48SLars Fredriksen     sendflg = 0;
3259b1aec48SLars Fredriksen 
3269b1aec48SLars Fredriksen     while (fgets(buf, STR_LEN, cfp) != NULL)
3279b1aec48SLars Fredriksen 	{
3289b1aec48SLars Fredriksen 	sp = strchr (buf, '\n');
3299b1aec48SLars Fredriksen 	if (sp)
3309f65f104SPeter Wemm 	    {
3319b1aec48SLars Fredriksen 	    *sp = '\0';
3329f65f104SPeter Wemm 	    }
3339b1aec48SLars Fredriksen 
3349b1aec48SLars Fredriksen 	linect++;
3359b1aec48SLars Fredriksen 	sp = buf;
3369b1aec48SLars Fredriksen 	while (*sp != '\0')
3379b1aec48SLars Fredriksen 	    {
3389b1aec48SLars Fredriksen 	    if (*sp == ' ' || *sp == '\t')
3399b1aec48SLars Fredriksen 		{
3409b1aec48SLars Fredriksen 		++sp;
3419b1aec48SLars Fredriksen 		continue;
3429b1aec48SLars Fredriksen 		}
3439b1aec48SLars Fredriksen 
3449b1aec48SLars Fredriksen 	    if (*sp == '"' || *sp == '\'')
3459b1aec48SLars Fredriksen 		{
3469b1aec48SLars Fredriksen 		quote = *sp++;
3479b1aec48SLars Fredriksen 		arg = sp;
3489b1aec48SLars Fredriksen 		while (*sp != quote)
3499b1aec48SLars Fredriksen 		    {
3509b1aec48SLars Fredriksen 		    if (*sp == '\0')
3519b1aec48SLars Fredriksen 			{
3529b1aec48SLars Fredriksen 			syslog (LOG_ERR, "unterminated quote (line %d)",
3539b1aec48SLars Fredriksen 				linect);
3549b1aec48SLars Fredriksen 			terminate (1);
3559b1aec48SLars Fredriksen 			}
3569b1aec48SLars Fredriksen 
3579b1aec48SLars Fredriksen 		    if (*sp++ == '\\')
3589f65f104SPeter Wemm 		        {
3599b1aec48SLars Fredriksen 			if (*sp != '\0')
3609f65f104SPeter Wemm 			    {
3619b1aec48SLars Fredriksen 			    ++sp;
3629b1aec48SLars Fredriksen 			    }
3639b1aec48SLars Fredriksen 		        }
3649f65f104SPeter Wemm 		    }
3659f65f104SPeter Wemm 		}
3669b1aec48SLars Fredriksen 	    else
3679b1aec48SLars Fredriksen 		{
3689b1aec48SLars Fredriksen 		arg = sp;
3699b1aec48SLars Fredriksen 		while (*sp != '\0' && *sp != ' ' && *sp != '\t')
3709f65f104SPeter Wemm 		    {
3719b1aec48SLars Fredriksen 		    ++sp;
3729b1aec48SLars Fredriksen 		    }
3739f65f104SPeter Wemm 		}
3749b1aec48SLars Fredriksen 
3759b1aec48SLars Fredriksen 	    if (*sp != '\0')
3769f65f104SPeter Wemm 	        {
3779b1aec48SLars Fredriksen 		*sp++ = '\0';
3789f65f104SPeter Wemm 	        }
3799b1aec48SLars Fredriksen 
3809b1aec48SLars Fredriksen 	    if (sendflg)
3819b1aec48SLars Fredriksen 		{
3829b1aec48SLars Fredriksen 		chat_send (arg);
3839b1aec48SLars Fredriksen 		}
3849b1aec48SLars Fredriksen 	    else
3859b1aec48SLars Fredriksen 		{
3869b1aec48SLars Fredriksen 		chat_expect (arg);
3879b1aec48SLars Fredriksen 		}
3889b1aec48SLars Fredriksen 	    sendflg = !sendflg;
3899b1aec48SLars Fredriksen 	    }
3909b1aec48SLars Fredriksen 	}
3919b1aec48SLars Fredriksen     fclose (cfp);
3929b1aec48SLars Fredriksen     }
3939b1aec48SLars Fredriksen 
3949b1aec48SLars Fredriksen /*
3959b1aec48SLars Fredriksen  *	We got an error parsing the command line.
3969b1aec48SLars Fredriksen  */
3979b1aec48SLars Fredriksen void usage()
3989b1aec48SLars Fredriksen     {
3999b1aec48SLars Fredriksen     fprintf(stderr, "\
4009f65f104SPeter Wemm Usage: %s [-v] [-t timeout] [-r report-file] {-f chat-file | chat-script}\n",
4019b1aec48SLars Fredriksen 	    program_name);
4029b1aec48SLars Fredriksen     exit(1);
4039b1aec48SLars Fredriksen     }
4049b1aec48SLars Fredriksen 
4059b1aec48SLars Fredriksen char line[256];
4069b1aec48SLars Fredriksen char *p;
4079b1aec48SLars Fredriksen 
4089b1aec48SLars Fredriksen void logf (str)
4099b1aec48SLars Fredriksen const char *str;
4109b1aec48SLars Fredriksen     {
4119b1aec48SLars Fredriksen     p = line + strlen(line);
4129b1aec48SLars Fredriksen     strcat (p, str);
4139b1aec48SLars Fredriksen 
4149b1aec48SLars Fredriksen     if (str[strlen(str)-1] == '\n')
4159b1aec48SLars Fredriksen 	{
4169b1aec48SLars Fredriksen 	syslog (LOG_INFO, "%s", line);
4179b1aec48SLars Fredriksen 	line[0] = 0;
4189b1aec48SLars Fredriksen 	}
4199b1aec48SLars Fredriksen     }
4209b1aec48SLars Fredriksen 
4219b1aec48SLars Fredriksen void logflush()
4229b1aec48SLars Fredriksen     {
4239b1aec48SLars Fredriksen     if (line[0] != 0)
4249b1aec48SLars Fredriksen 	{
4259b1aec48SLars Fredriksen 	syslog(LOG_INFO, "%s", line);
4269b1aec48SLars Fredriksen 	line[0] = 0;
4279b1aec48SLars Fredriksen         }
4289b1aec48SLars Fredriksen     }
4299b1aec48SLars Fredriksen 
4309b1aec48SLars Fredriksen /*
4319f65f104SPeter Wemm  *	Terminate with an error.
4329b1aec48SLars Fredriksen  */
4339b1aec48SLars Fredriksen void die()
4349b1aec48SLars Fredriksen     {
4359b1aec48SLars Fredriksen     terminate(1);
4369b1aec48SLars Fredriksen     }
4379b1aec48SLars Fredriksen 
4389b1aec48SLars Fredriksen /*
4399b1aec48SLars Fredriksen  *	Print an error message and terminate.
4409b1aec48SLars Fredriksen  */
4419b1aec48SLars Fredriksen 
4429b1aec48SLars Fredriksen void fatal (msg)
4439b1aec48SLars Fredriksen const char *msg;
4449b1aec48SLars Fredriksen     {
4459b1aec48SLars Fredriksen     syslog(LOG_ERR, "%s", msg);
4469f65f104SPeter Wemm     terminate(2);
4479b1aec48SLars Fredriksen     }
4489b1aec48SLars Fredriksen 
4499b1aec48SLars Fredriksen /*
4509b1aec48SLars Fredriksen  *	Print an error message along with the system error message and
4519b1aec48SLars Fredriksen  *	terminate.
4529b1aec48SLars Fredriksen  */
4539b1aec48SLars Fredriksen 
4549b1aec48SLars Fredriksen void sysfatal (msg)
4559b1aec48SLars Fredriksen const char *msg;
4569b1aec48SLars Fredriksen     {
4579b1aec48SLars Fredriksen     syslog(LOG_ERR, "%s: %m", msg);
4589f65f104SPeter Wemm     terminate(2);
4599b1aec48SLars Fredriksen     }
4609b1aec48SLars Fredriksen 
4619b1aec48SLars Fredriksen int alarmed = 0;
4629b1aec48SLars Fredriksen 
4639b1aec48SLars Fredriksen SIGTYPE sigalrm(signo)
4649b1aec48SLars Fredriksen int signo;
4659b1aec48SLars Fredriksen     {
4669b1aec48SLars Fredriksen     int flags;
4679b1aec48SLars Fredriksen 
4689b1aec48SLars Fredriksen     alarm(1);
4699b1aec48SLars Fredriksen     alarmed = 1;		/* Reset alarm to avoid race window */
4709b1aec48SLars Fredriksen     signal(SIGALRM, sigalrm);	/* that can cause hanging in read() */
4719b1aec48SLars Fredriksen 
4729b1aec48SLars Fredriksen     logflush();
4739b1aec48SLars Fredriksen     if ((flags = fcntl(0, F_GETFL, 0)) == -1)
4749f65f104SPeter Wemm         {
4759b1aec48SLars Fredriksen 	sysfatal("Can't get file mode flags on stdin");
4769f65f104SPeter Wemm         }
4779b1aec48SLars Fredriksen     else
4789f65f104SPeter Wemm         {
4799f65f104SPeter Wemm 	if (fcntl(0, F_SETFL, flags | O_NONBLOCK) == -1)
4809f65f104SPeter Wemm 	    {
4819b1aec48SLars Fredriksen 	    sysfatal("Can't set file mode flags on stdin");
4829f65f104SPeter Wemm 	    }
4839f65f104SPeter Wemm         }
4849b1aec48SLars Fredriksen 
4859b1aec48SLars Fredriksen     if (verbose)
4869b1aec48SLars Fredriksen 	{
4879b1aec48SLars Fredriksen 	syslog(LOG_INFO, "alarm");
4889b1aec48SLars Fredriksen 	}
4899b1aec48SLars Fredriksen     }
4909b1aec48SLars Fredriksen 
4919b1aec48SLars Fredriksen void unalarm()
4929b1aec48SLars Fredriksen     {
4939b1aec48SLars Fredriksen     int flags;
4949b1aec48SLars Fredriksen 
4959b1aec48SLars Fredriksen     if ((flags = fcntl(0, F_GETFL, 0)) == -1)
4969f65f104SPeter Wemm         {
4979b1aec48SLars Fredriksen 	sysfatal("Can't get file mode flags on stdin");
4989f65f104SPeter Wemm         }
4999b1aec48SLars Fredriksen     else
5009f65f104SPeter Wemm         {
5019f65f104SPeter Wemm 	if (fcntl(0, F_SETFL, flags & ~O_NONBLOCK) == -1)
5029f65f104SPeter Wemm 	    {
5039b1aec48SLars Fredriksen 	    sysfatal("Can't set file mode flags on stdin");
5049b1aec48SLars Fredriksen 	    }
5059f65f104SPeter Wemm         }
5069f65f104SPeter Wemm     }
5079b1aec48SLars Fredriksen 
5089b1aec48SLars Fredriksen SIGTYPE sigint(signo)
5099b1aec48SLars Fredriksen int signo;
5109b1aec48SLars Fredriksen     {
5119b1aec48SLars Fredriksen     fatal("SIGINT");
5129b1aec48SLars Fredriksen     }
5139b1aec48SLars Fredriksen 
5149b1aec48SLars Fredriksen SIGTYPE sigterm(signo)
5159b1aec48SLars Fredriksen int signo;
5169b1aec48SLars Fredriksen     {
5179b1aec48SLars Fredriksen     fatal("SIGTERM");
5189b1aec48SLars Fredriksen     }
5199b1aec48SLars Fredriksen 
5209b1aec48SLars Fredriksen SIGTYPE sighup(signo)
5219b1aec48SLars Fredriksen int signo;
5229b1aec48SLars Fredriksen     {
5239b1aec48SLars Fredriksen     fatal("SIGHUP");
5249b1aec48SLars Fredriksen     }
5259b1aec48SLars Fredriksen 
5269b1aec48SLars Fredriksen void init()
5279b1aec48SLars Fredriksen     {
5289b1aec48SLars Fredriksen     signal(SIGINT, sigint);
5299b1aec48SLars Fredriksen     signal(SIGTERM, sigterm);
5309b1aec48SLars Fredriksen     signal(SIGHUP, sighup);
5319b1aec48SLars Fredriksen 
5329b1aec48SLars Fredriksen     set_tty_parameters();
5339b1aec48SLars Fredriksen     signal(SIGALRM, sigalrm);
5349b1aec48SLars Fredriksen     alarm(0);
5359b1aec48SLars Fredriksen     alarmed = 0;
5369b1aec48SLars Fredriksen     }
5379b1aec48SLars Fredriksen 
5389b1aec48SLars Fredriksen void set_tty_parameters()
5399b1aec48SLars Fredriksen     {
5409f65f104SPeter Wemm #if defined(get_term_param)
5419f65f104SPeter Wemm     term_parms t;
5429b1aec48SLars Fredriksen 
5439f65f104SPeter Wemm     if (get_term_param (&t) < 0)
5449f65f104SPeter Wemm         {
5459b1aec48SLars Fredriksen 	sysfatal("Can't get terminal parameters");
5469f65f104SPeter Wemm         }
5479b1aec48SLars Fredriksen 
5489b1aec48SLars Fredriksen     saved_tty_parameters = t;
5499b1aec48SLars Fredriksen     have_tty_parameters  = 1;
5509b1aec48SLars Fredriksen 
5519b1aec48SLars Fredriksen     t.c_iflag     |= IGNBRK | ISTRIP | IGNPAR;
5529b1aec48SLars Fredriksen     t.c_oflag      = 0;
5539b1aec48SLars Fredriksen     t.c_lflag      = 0;
5549f65f104SPeter Wemm     t.c_cc[VERASE] =
5559f65f104SPeter Wemm     t.c_cc[VKILL]  = 0;
5569b1aec48SLars Fredriksen     t.c_cc[VMIN]   = 1;
5579b1aec48SLars Fredriksen     t.c_cc[VTIME]  = 0;
5589b1aec48SLars Fredriksen 
5599f65f104SPeter Wemm     if (set_term_param (&t) < 0)
5609f65f104SPeter Wemm         {
5619b1aec48SLars Fredriksen 	sysfatal("Can't set terminal parameters");
5629f65f104SPeter Wemm         }
5639b1aec48SLars Fredriksen #endif
5649b1aec48SLars Fredriksen     }
5659b1aec48SLars Fredriksen 
5669b1aec48SLars Fredriksen void break_sequence()
5679b1aec48SLars Fredriksen     {
5689b1aec48SLars Fredriksen #ifdef TERMIOS
5699b1aec48SLars Fredriksen     tcsendbreak (0, 0);
5709b1aec48SLars Fredriksen #endif
5719b1aec48SLars Fredriksen     }
5729b1aec48SLars Fredriksen 
5739b1aec48SLars Fredriksen void terminate(status)
5749b1aec48SLars Fredriksen int status;
5759b1aec48SLars Fredriksen     {
5769f65f104SPeter Wemm     if (report_file != (char *) 0 && report_fp != (FILE *) NULL)
5779f65f104SPeter Wemm         {
5789f65f104SPeter Wemm 	if (verbose)
5799f65f104SPeter Wemm 	    {
5809f65f104SPeter Wemm 	    fprintf (report_fp, "Closing \"%s\".\n", report_file);
5819f65f104SPeter Wemm 	    }
5829f65f104SPeter Wemm 	fclose (report_fp);
5839f65f104SPeter Wemm 	report_fp = (FILE*) NULL;
5849f65f104SPeter Wemm         }
5859f65f104SPeter Wemm 
5869f65f104SPeter Wemm #if defined(get_term_param)
5879f65f104SPeter Wemm     if (have_tty_parameters)
5889f65f104SPeter Wemm         {
5899f65f104SPeter Wemm 	if (set_term_param (&saved_tty_parameters) < 0)
5909f65f104SPeter Wemm 	    {
5919b1aec48SLars Fredriksen 	    syslog(LOG_ERR, "Can't restore terminal parameters: %m");
5929b1aec48SLars Fredriksen 	    exit(1);
5939b1aec48SLars Fredriksen 	    }
5949f65f104SPeter Wemm         }
5959f65f104SPeter Wemm #endif
5969f65f104SPeter Wemm 
5979b1aec48SLars Fredriksen     exit(status);
5989b1aec48SLars Fredriksen     }
5999b1aec48SLars Fredriksen 
6009b1aec48SLars Fredriksen /*
6019b1aec48SLars Fredriksen  *	'Clean up' this string.
6029b1aec48SLars Fredriksen  */
6039b1aec48SLars Fredriksen char *clean(s, sending)
6049b1aec48SLars Fredriksen register char *s;
6059b1aec48SLars Fredriksen int sending;
6069b1aec48SLars Fredriksen     {
6079b1aec48SLars Fredriksen     char temp[STR_LEN], cur_chr;
6089b1aec48SLars Fredriksen     register char *s1;
6099b1aec48SLars Fredriksen     int add_return = sending;
6109b1aec48SLars Fredriksen #define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
6119b1aec48SLars Fredriksen 
6129b1aec48SLars Fredriksen     s1 = temp;
6139b1aec48SLars Fredriksen     while (*s)
6149b1aec48SLars Fredriksen 	{
6159b1aec48SLars Fredriksen 	cur_chr = *s++;
6169b1aec48SLars Fredriksen 	if (cur_chr == '^')
6179b1aec48SLars Fredriksen 	    {
6189b1aec48SLars Fredriksen 	    cur_chr = *s++;
6199b1aec48SLars Fredriksen 	    if (cur_chr == '\0')
6209b1aec48SLars Fredriksen 		{
6219b1aec48SLars Fredriksen 		*s1++ = '^';
6229b1aec48SLars Fredriksen 		break;
6239b1aec48SLars Fredriksen 		}
6249b1aec48SLars Fredriksen 	    cur_chr &= 0x1F;
6259b1aec48SLars Fredriksen 	    if (cur_chr != 0)
6269f65f104SPeter Wemm 	        {
6279b1aec48SLars Fredriksen 		*s1++ = cur_chr;
6289f65f104SPeter Wemm 	        }
6299b1aec48SLars Fredriksen 	    continue;
6309b1aec48SLars Fredriksen 	    }
6319b1aec48SLars Fredriksen 
6329b1aec48SLars Fredriksen 	if (cur_chr != '\\')
6339b1aec48SLars Fredriksen 	    {
6349b1aec48SLars Fredriksen 	    *s1++ = cur_chr;
6359b1aec48SLars Fredriksen 	    continue;
6369b1aec48SLars Fredriksen 	    }
6379b1aec48SLars Fredriksen 
6389b1aec48SLars Fredriksen 	cur_chr = *s++;
6399b1aec48SLars Fredriksen 	if (cur_chr == '\0')
6409b1aec48SLars Fredriksen 	    {
6419b1aec48SLars Fredriksen 	    if (sending)
6429b1aec48SLars Fredriksen 		{
6439b1aec48SLars Fredriksen 		*s1++ = '\\';
6449b1aec48SLars Fredriksen 		*s1++ = '\\';
6459b1aec48SLars Fredriksen 		}
6469b1aec48SLars Fredriksen 	    break;
6479b1aec48SLars Fredriksen 	    }
6489b1aec48SLars Fredriksen 
6499b1aec48SLars Fredriksen 	switch (cur_chr)
6509b1aec48SLars Fredriksen 	    {
6519b1aec48SLars Fredriksen 	case 'b':
6529b1aec48SLars Fredriksen 	    *s1++ = '\b';
6539b1aec48SLars Fredriksen 	    break;
6549b1aec48SLars Fredriksen 
6559b1aec48SLars Fredriksen 	case 'c':
6569b1aec48SLars Fredriksen 	    if (sending && *s == '\0')
6579f65f104SPeter Wemm 	        {
6589b1aec48SLars Fredriksen 		add_return = 0;
6599f65f104SPeter Wemm 	        }
6609b1aec48SLars Fredriksen 	    else
6619f65f104SPeter Wemm 	        {
6629b1aec48SLars Fredriksen 		*s1++ = cur_chr;
6639f65f104SPeter Wemm 	        }
6649b1aec48SLars Fredriksen 	    break;
6659b1aec48SLars Fredriksen 
6669b1aec48SLars Fredriksen 	case '\\':
6679b1aec48SLars Fredriksen 	case 'K':
6689b1aec48SLars Fredriksen 	case 'p':
6699b1aec48SLars Fredriksen 	case 'd':
6709b1aec48SLars Fredriksen 	    if (sending)
6719f65f104SPeter Wemm 	        {
6729b1aec48SLars Fredriksen 		*s1++ = '\\';
6739f65f104SPeter Wemm 	        }
6749b1aec48SLars Fredriksen 
6759b1aec48SLars Fredriksen 	    *s1++ = cur_chr;
6769b1aec48SLars Fredriksen 	    break;
6779b1aec48SLars Fredriksen 
6789b1aec48SLars Fredriksen 	case 'q':
6799b1aec48SLars Fredriksen 	    quiet = ! quiet;
6809b1aec48SLars Fredriksen 	    break;
6819b1aec48SLars Fredriksen 
6829b1aec48SLars Fredriksen 	case 'r':
6839b1aec48SLars Fredriksen 	    *s1++ = '\r';
6849b1aec48SLars Fredriksen 	    break;
6859b1aec48SLars Fredriksen 
6869b1aec48SLars Fredriksen 	case 'n':
6879b1aec48SLars Fredriksen 	    *s1++ = '\n';
6889b1aec48SLars Fredriksen 	    break;
6899b1aec48SLars Fredriksen 
6909b1aec48SLars Fredriksen 	case 's':
6919b1aec48SLars Fredriksen 	    *s1++ = ' ';
6929b1aec48SLars Fredriksen 	    break;
6939b1aec48SLars Fredriksen 
6949b1aec48SLars Fredriksen 	case 't':
6959b1aec48SLars Fredriksen 	    *s1++ = '\t';
6969b1aec48SLars Fredriksen 	    break;
6979b1aec48SLars Fredriksen 
6989b1aec48SLars Fredriksen 	case 'N':
6999b1aec48SLars Fredriksen 	    if (sending)
7009b1aec48SLars Fredriksen 		{
7019b1aec48SLars Fredriksen 		*s1++ = '\\';
7029b1aec48SLars Fredriksen 		*s1++ = '\0';
7039b1aec48SLars Fredriksen 		}
7049b1aec48SLars Fredriksen 	    else
7059f65f104SPeter Wemm 	        {
7069b1aec48SLars Fredriksen 		*s1++ = 'N';
7079f65f104SPeter Wemm 	        }
7089b1aec48SLars Fredriksen 	    break;
7099b1aec48SLars Fredriksen 
7109b1aec48SLars Fredriksen 	default:
7119b1aec48SLars Fredriksen 	    if (isoctal (cur_chr))
7129b1aec48SLars Fredriksen 		{
7139b1aec48SLars Fredriksen 		cur_chr &= 0x07;
7149b1aec48SLars Fredriksen 		if (isoctal (*s))
7159b1aec48SLars Fredriksen 		    {
7169b1aec48SLars Fredriksen 		    cur_chr <<= 3;
7179b1aec48SLars Fredriksen 		    cur_chr |= *s++ - '0';
7189b1aec48SLars Fredriksen 		    if (isoctal (*s))
7199b1aec48SLars Fredriksen 			{
7209b1aec48SLars Fredriksen 			cur_chr <<= 3;
7219b1aec48SLars Fredriksen 			cur_chr |= *s++ - '0';
7229b1aec48SLars Fredriksen 			}
7239b1aec48SLars Fredriksen 		    }
7249b1aec48SLars Fredriksen 
7259b1aec48SLars Fredriksen 		if (cur_chr != 0 || sending)
7269b1aec48SLars Fredriksen 		    {
7279b1aec48SLars Fredriksen 		    if (sending && (cur_chr == '\\' || cur_chr == 0))
7289f65f104SPeter Wemm 		        {
7299b1aec48SLars Fredriksen 			*s1++ = '\\';
7309f65f104SPeter Wemm 		        }
7319b1aec48SLars Fredriksen 		    *s1++ = cur_chr;
7329b1aec48SLars Fredriksen 		    }
7339b1aec48SLars Fredriksen 		break;
7349b1aec48SLars Fredriksen 		}
7359b1aec48SLars Fredriksen 
7369b1aec48SLars Fredriksen 	    if (sending)
7379f65f104SPeter Wemm 	        {
7389b1aec48SLars Fredriksen 		*s1++ = '\\';
7399f65f104SPeter Wemm 	        }
7409b1aec48SLars Fredriksen 	    *s1++ = cur_chr;
7419b1aec48SLars Fredriksen 	    break;
7429b1aec48SLars Fredriksen 	    }
7439b1aec48SLars Fredriksen 	}
7449b1aec48SLars Fredriksen 
7459b1aec48SLars Fredriksen     if (add_return)
7469f65f104SPeter Wemm         {
7479b1aec48SLars Fredriksen 	*s1++ = '\r';
7489f65f104SPeter Wemm         }
7499b1aec48SLars Fredriksen 
7509b1aec48SLars Fredriksen     *s1++ = '\0'; /* guarantee closure */
7519b1aec48SLars Fredriksen     *s1++ = '\0'; /* terminate the string */
7529b1aec48SLars Fredriksen     return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */
7539b1aec48SLars Fredriksen     }
7549b1aec48SLars Fredriksen 
7559b1aec48SLars Fredriksen /*
7569b1aec48SLars Fredriksen  * Process the expect string
7579b1aec48SLars Fredriksen  */
7589b1aec48SLars Fredriksen void chat_expect(s)
7599b1aec48SLars Fredriksen register char *s;
7609b1aec48SLars Fredriksen     {
7619b1aec48SLars Fredriksen     if (strcmp(s, "ABORT") == 0)
7629b1aec48SLars Fredriksen 	{
7639b1aec48SLars Fredriksen 	++abort_next;
7649b1aec48SLars Fredriksen 	return;
7659b1aec48SLars Fredriksen 	}
7669b1aec48SLars Fredriksen 
7679f65f104SPeter Wemm     if (strcmp(s, "REPORT") == 0)
7689f65f104SPeter Wemm 	{
7699f65f104SPeter Wemm 	++report_next;
7709f65f104SPeter Wemm 	return;
7719f65f104SPeter Wemm 	}
7729f65f104SPeter Wemm 
7739b1aec48SLars Fredriksen     if (strcmp(s, "TIMEOUT") == 0)
7749b1aec48SLars Fredriksen 	{
7759b1aec48SLars Fredriksen 	++timeout_next;
7769b1aec48SLars Fredriksen 	return;
7779b1aec48SLars Fredriksen 	}
7789b1aec48SLars Fredriksen 
7799b1aec48SLars Fredriksen     while (*s)
7809b1aec48SLars Fredriksen 	{
7819b1aec48SLars Fredriksen 	register char *hyphen;
7829b1aec48SLars Fredriksen 
7839b1aec48SLars Fredriksen 	for (hyphen = s; *hyphen; ++hyphen)
7849f65f104SPeter Wemm 	    {
7859b1aec48SLars Fredriksen 	    if (*hyphen == '-')
7869f65f104SPeter Wemm 	        {
7879b1aec48SLars Fredriksen 		if (hyphen == s || hyphen[-1] != '\\')
7889f65f104SPeter Wemm 		    {
7899b1aec48SLars Fredriksen 		    break;
7909f65f104SPeter Wemm 		    }
7919f65f104SPeter Wemm 	        }
7929f65f104SPeter Wemm 	    }
7939b1aec48SLars Fredriksen 
7949b1aec48SLars Fredriksen 	if (*hyphen == '-')
7959b1aec48SLars Fredriksen 	    {
7969b1aec48SLars Fredriksen 	    *hyphen = '\0';
7979b1aec48SLars Fredriksen 
7989b1aec48SLars Fredriksen 	    if (get_string(s))
7999f65f104SPeter Wemm 	        {
8009b1aec48SLars Fredriksen 		return;
8019f65f104SPeter Wemm 	        }
8029b1aec48SLars Fredriksen 	    else
8039b1aec48SLars Fredriksen 		{
8049b1aec48SLars Fredriksen 		s = hyphen + 1;
8059b1aec48SLars Fredriksen 
8069b1aec48SLars Fredriksen 		for (hyphen = s; *hyphen; ++hyphen)
8079f65f104SPeter Wemm 		    {
8089b1aec48SLars Fredriksen 		    if (*hyphen == '-')
8099f65f104SPeter Wemm 		        {
8109b1aec48SLars Fredriksen 			if (hyphen == s || hyphen[-1] != '\\')
8119f65f104SPeter Wemm 			    {
8129b1aec48SLars Fredriksen 			    break;
8139f65f104SPeter Wemm 			    }
8149f65f104SPeter Wemm 		        }
8159f65f104SPeter Wemm 		    }
8169b1aec48SLars Fredriksen 
8179b1aec48SLars Fredriksen 		if (*hyphen == '-')
8189b1aec48SLars Fredriksen 		    {
8199b1aec48SLars Fredriksen 		    *hyphen = '\0';
8209b1aec48SLars Fredriksen 
8219b1aec48SLars Fredriksen 		    chat_send(s);
8229b1aec48SLars Fredriksen 		    s = hyphen + 1;
8239b1aec48SLars Fredriksen 		    }
8249b1aec48SLars Fredriksen 		else
8259b1aec48SLars Fredriksen 		    {
8269b1aec48SLars Fredriksen 		    chat_send(s);
8279b1aec48SLars Fredriksen 		    return;
8289b1aec48SLars Fredriksen 		    }
8299b1aec48SLars Fredriksen 		}
8309b1aec48SLars Fredriksen 	    }
8319b1aec48SLars Fredriksen 	else
8329f65f104SPeter Wemm 	    {
8339b1aec48SLars Fredriksen 	    if (get_string(s))
8349f65f104SPeter Wemm 	        {
8359b1aec48SLars Fredriksen 		return;
8369f65f104SPeter Wemm 	        }
8379b1aec48SLars Fredriksen 	    else
8389b1aec48SLars Fredriksen 		{
8399b1aec48SLars Fredriksen 		if (fail_reason)
8409f65f104SPeter Wemm 		    {
8419b1aec48SLars Fredriksen 		    syslog(LOG_INFO, "Failed (%s)", fail_reason);
8429f65f104SPeter Wemm 		    }
8439b1aec48SLars Fredriksen 		else
8449f65f104SPeter Wemm 		    {
8459b1aec48SLars Fredriksen 		    syslog(LOG_INFO, "Failed");
8469f65f104SPeter Wemm 		    }
8479b1aec48SLars Fredriksen 
8489f65f104SPeter Wemm 		terminate(exit_code);
8499f65f104SPeter Wemm 		}
8509b1aec48SLars Fredriksen 	    }
8519b1aec48SLars Fredriksen 	}
8529b1aec48SLars Fredriksen     }
8539b1aec48SLars Fredriksen 
8549b1aec48SLars Fredriksen char *character(c)
8559f65f104SPeter Wemm int c;
8569b1aec48SLars Fredriksen     {
8579b1aec48SLars Fredriksen     static char string[10];
8589b1aec48SLars Fredriksen     char *meta;
8599b1aec48SLars Fredriksen 
8609b1aec48SLars Fredriksen     meta = (c & 0x80) ? "M-" : "";
8619b1aec48SLars Fredriksen     c &= 0x7F;
8629b1aec48SLars Fredriksen 
8639b1aec48SLars Fredriksen     if (c < 32)
8649f65f104SPeter Wemm         {
8659b1aec48SLars Fredriksen 	sprintf(string, "%s^%c", meta, (int)c + '@');
8669f65f104SPeter Wemm         }
8679b1aec48SLars Fredriksen     else
8689f65f104SPeter Wemm         {
8699b1aec48SLars Fredriksen 	if (c == 127)
8709f65f104SPeter Wemm 	    {
8719b1aec48SLars Fredriksen 	    sprintf(string, "%s^?", meta);
8729f65f104SPeter Wemm 	    }
8739b1aec48SLars Fredriksen 	else
8749f65f104SPeter Wemm 	    {
8759b1aec48SLars Fredriksen 	    sprintf(string, "%s%c", meta, c);
8769f65f104SPeter Wemm 	    }
8779f65f104SPeter Wemm         }
8789b1aec48SLars Fredriksen 
8799b1aec48SLars Fredriksen     return (string);
8809b1aec48SLars Fredriksen     }
8819b1aec48SLars Fredriksen 
8829b1aec48SLars Fredriksen /*
8839b1aec48SLars Fredriksen  *  process the reply string
8849b1aec48SLars Fredriksen  */
8859b1aec48SLars Fredriksen void chat_send (s)
8869b1aec48SLars Fredriksen register char *s;
8879b1aec48SLars Fredriksen     {
8889b1aec48SLars Fredriksen     if (abort_next)
8899b1aec48SLars Fredriksen         {
8909b1aec48SLars Fredriksen 	char *s1;
8919b1aec48SLars Fredriksen 
8929b1aec48SLars Fredriksen 	abort_next = 0;
8939b1aec48SLars Fredriksen 
8949b1aec48SLars Fredriksen 	if (n_aborts >= MAX_ABORTS)
8959f65f104SPeter Wemm 	    {
8969b1aec48SLars Fredriksen 	    fatal("Too many ABORT strings");
8979f65f104SPeter Wemm 	    }
8989b1aec48SLars Fredriksen 
8999b1aec48SLars Fredriksen 	s1 = clean(s, 0);
9009b1aec48SLars Fredriksen 
9019f65f104SPeter Wemm 	if (strlen(s1) > strlen(s)
9029f65f104SPeter Wemm 	    || strlen(s1) + 1 > sizeof(fail_buffer))
9039b1aec48SLars Fredriksen 	    {
9049b1aec48SLars Fredriksen 	    syslog(LOG_WARNING, "Illegal or too-long ABORT string ('%s')", s);
9059b1aec48SLars Fredriksen 	    die();
9069b1aec48SLars Fredriksen 	    }
9079b1aec48SLars Fredriksen 
9089b1aec48SLars Fredriksen 	abort_string[n_aborts++] = s1;
9099b1aec48SLars Fredriksen 
9109b1aec48SLars Fredriksen 	if (verbose)
9119b1aec48SLars Fredriksen 	    {
9129b1aec48SLars Fredriksen 	    logf("abort on (");
9139b1aec48SLars Fredriksen 
9149b1aec48SLars Fredriksen 	    for (s1 = s; *s1; ++s1)
9159f65f104SPeter Wemm 	        {
9169b1aec48SLars Fredriksen 		logf(character(*s1));
9179f65f104SPeter Wemm 	        }
9189b1aec48SLars Fredriksen 
9199b1aec48SLars Fredriksen 	    logf(")\n");
9209b1aec48SLars Fredriksen 	    }
9219f65f104SPeter Wemm 	return;
9229b1aec48SLars Fredriksen 	}
9239f65f104SPeter Wemm 
9249f65f104SPeter Wemm     if (report_next)
9259f65f104SPeter Wemm         {
9269f65f104SPeter Wemm 	char *s1;
9279f65f104SPeter Wemm 
9289f65f104SPeter Wemm 	report_next = 0;
9299f65f104SPeter Wemm 	if (n_reports >= MAX_REPORTS)
9309f65f104SPeter Wemm 	    {
9319f65f104SPeter Wemm 	    fatal("Too many REPORT strings");
9329f65f104SPeter Wemm 	    }
9339f65f104SPeter Wemm 
9349f65f104SPeter Wemm 	s1 = clean(s, 0);
9359f65f104SPeter Wemm 
9369f65f104SPeter Wemm 	if (strlen(s1) > strlen(s) || strlen(s1) > sizeof fail_buffer - 1)
9379f65f104SPeter Wemm 	    {
9389f65f104SPeter Wemm 	    syslog(LOG_WARNING, "Illegal or too-long REPORT string ('%s')", s);
9399f65f104SPeter Wemm 	    die();
9409f65f104SPeter Wemm 	    }
9419f65f104SPeter Wemm 
9429f65f104SPeter Wemm 	report_string[n_reports++] = s1;
9439f65f104SPeter Wemm 
9449f65f104SPeter Wemm 	if (verbose)
9459f65f104SPeter Wemm 	    {
9469f65f104SPeter Wemm 	    logf("report (");
9479f65f104SPeter Wemm 	    s1 = s;
9489f65f104SPeter Wemm 	    while (*s1)
9499f65f104SPeter Wemm 	        {
9509f65f104SPeter Wemm 		logf(character(*s1));
9519f65f104SPeter Wemm 		++s1;
9529f65f104SPeter Wemm 	        }
9539f65f104SPeter Wemm 	    logf(")\n");
9549f65f104SPeter Wemm 	    }
9559f65f104SPeter Wemm 	return;
9569f65f104SPeter Wemm         }
9579f65f104SPeter Wemm 
9589b1aec48SLars Fredriksen     if (timeout_next)
9599b1aec48SLars Fredriksen         {
9609b1aec48SLars Fredriksen 	timeout_next = 0;
9619b1aec48SLars Fredriksen 	timeout = atoi(s);
9629b1aec48SLars Fredriksen 
9639b1aec48SLars Fredriksen 	if (timeout <= 0)
9649f65f104SPeter Wemm 	    {
9659b1aec48SLars Fredriksen 	    timeout = DEFAULT_CHAT_TIMEOUT;
9669f65f104SPeter Wemm 	    }
9679b1aec48SLars Fredriksen 
9689b1aec48SLars Fredriksen 	if (verbose)
9699b1aec48SLars Fredriksen 	    {
9709b1aec48SLars Fredriksen 	    syslog(LOG_INFO, "timeout set to %d seconds", timeout);
9719b1aec48SLars Fredriksen 	    }
9729f65f104SPeter Wemm 	return;
9739f65f104SPeter Wemm         }
9749f65f104SPeter Wemm 
9759f65f104SPeter Wemm     if (strcmp(s, "EOT") == 0)
9769f65f104SPeter Wemm         {
9779f65f104SPeter Wemm 	s = "^D\\c";
9789b1aec48SLars Fredriksen         }
9799b1aec48SLars Fredriksen     else
9809b1aec48SLars Fredriksen         {
9819b1aec48SLars Fredriksen 	if (strcmp(s, "BREAK") == 0)
9829f65f104SPeter Wemm 	    {
9839b1aec48SLars Fredriksen 	    s = "\\K\\c";
9849f65f104SPeter Wemm 	    }
9859f65f104SPeter Wemm         }
9869f65f104SPeter Wemm 
9879b1aec48SLars Fredriksen     if (!put_string(s))
9889b1aec48SLars Fredriksen         {
9899b1aec48SLars Fredriksen 	syslog(LOG_INFO, "Failed");
9909b1aec48SLars Fredriksen 	terminate(1);
9919b1aec48SLars Fredriksen         }
9929b1aec48SLars Fredriksen     }
9939b1aec48SLars Fredriksen 
9949b1aec48SLars Fredriksen int get_char()
9959b1aec48SLars Fredriksen     {
9969b1aec48SLars Fredriksen     int status;
9979b1aec48SLars Fredriksen     char c;
9989b1aec48SLars Fredriksen 
9999b1aec48SLars Fredriksen     status = read(0, &c, 1);
10009b1aec48SLars Fredriksen 
10019b1aec48SLars Fredriksen     switch (status)
10029b1aec48SLars Fredriksen         {
10039b1aec48SLars Fredriksen     case 1:
10049b1aec48SLars Fredriksen 	return ((int)c & 0x7F);
10059b1aec48SLars Fredriksen 
10069b1aec48SLars Fredriksen     default:
10079b1aec48SLars Fredriksen 	syslog(LOG_WARNING, "warning: read() on stdin returned %d",
10089b1aec48SLars Fredriksen 	       status);
10099b1aec48SLars Fredriksen 
10109b1aec48SLars Fredriksen     case -1:
10119b1aec48SLars Fredriksen 	if ((status = fcntl(0, F_GETFL, 0)) == -1)
10129f65f104SPeter Wemm 	    {
10139b1aec48SLars Fredriksen 	    sysfatal("Can't get file mode flags on stdin");
10149f65f104SPeter Wemm 	    }
10159b1aec48SLars Fredriksen 	else
10169f65f104SPeter Wemm 	    {
10179f65f104SPeter Wemm 	    if (fcntl(0, F_SETFL, status & ~O_NONBLOCK) == -1)
10189f65f104SPeter Wemm 	        {
10199b1aec48SLars Fredriksen 		sysfatal("Can't set file mode flags on stdin");
10209f65f104SPeter Wemm 	        }
10219f65f104SPeter Wemm 	    }
10229b1aec48SLars Fredriksen 
10239b1aec48SLars Fredriksen 	return (-1);
10249b1aec48SLars Fredriksen         }
10259b1aec48SLars Fredriksen     }
10269b1aec48SLars Fredriksen 
10279b1aec48SLars Fredriksen int put_char(c)
10289f65f104SPeter Wemm int c;
10299b1aec48SLars Fredriksen     {
10309b1aec48SLars Fredriksen     int status;
10319f65f104SPeter Wemm     char ch = c;
10329b1aec48SLars Fredriksen 
10339f65f104SPeter Wemm     usleep(10000);		/* inter-character typing delay (?) */
10349b1aec48SLars Fredriksen 
10359f65f104SPeter Wemm     status = write(1, &ch, 1);
10369b1aec48SLars Fredriksen 
10379b1aec48SLars Fredriksen     switch (status)
10389b1aec48SLars Fredriksen         {
10399b1aec48SLars Fredriksen     case 1:
10409b1aec48SLars Fredriksen 	return (0);
10419b1aec48SLars Fredriksen 
10429b1aec48SLars Fredriksen     default:
10439b1aec48SLars Fredriksen 	syslog(LOG_WARNING, "warning: write() on stdout returned %d",
10449b1aec48SLars Fredriksen 	       status);
10459b1aec48SLars Fredriksen 
10469b1aec48SLars Fredriksen     case -1:
10479b1aec48SLars Fredriksen 	if ((status = fcntl(0, F_GETFL, 0)) == -1)
10489f65f104SPeter Wemm 	    {
10499b1aec48SLars Fredriksen 	    sysfatal("Can't get file mode flags on stdin");
10509f65f104SPeter Wemm 	    }
10519b1aec48SLars Fredriksen 	else
10529f65f104SPeter Wemm 	    {
10539f65f104SPeter Wemm 	    if (fcntl(0, F_SETFL, status & ~O_NONBLOCK) == -1)
10549f65f104SPeter Wemm 	        {
10559b1aec48SLars Fredriksen 		sysfatal("Can't set file mode flags on stdin");
10569f65f104SPeter Wemm 	        }
10579f65f104SPeter Wemm 	    }
10589b1aec48SLars Fredriksen 
10599b1aec48SLars Fredriksen 	return (-1);
10609b1aec48SLars Fredriksen         }
10619b1aec48SLars Fredriksen     }
10629b1aec48SLars Fredriksen 
10639b1aec48SLars Fredriksen int write_char (c)
10649b1aec48SLars Fredriksen int c;
10659b1aec48SLars Fredriksen     {
10669b1aec48SLars Fredriksen     if (alarmed || put_char(c) < 0)
10679b1aec48SLars Fredriksen 	{
10689b1aec48SLars Fredriksen 	extern int errno;
10699b1aec48SLars Fredriksen 
10709f65f104SPeter Wemm 	alarm(0);
10719f65f104SPeter Wemm 	alarmed = 0;
10729b1aec48SLars Fredriksen 
10739b1aec48SLars Fredriksen 	if (verbose)
10749b1aec48SLars Fredriksen 	    {
10759b1aec48SLars Fredriksen 	    if (errno == EINTR || errno == EWOULDBLOCK)
10769f65f104SPeter Wemm 	        {
10779b1aec48SLars Fredriksen 		syslog(LOG_INFO, " -- write timed out");
10789f65f104SPeter Wemm 	        }
10799b1aec48SLars Fredriksen 	    else
10809f65f104SPeter Wemm 	        {
10819b1aec48SLars Fredriksen 		syslog(LOG_INFO, " -- write failed: %m");
10829b1aec48SLars Fredriksen 	        }
10839f65f104SPeter Wemm 	    }
10849b1aec48SLars Fredriksen 	return (0);
10859b1aec48SLars Fredriksen 	}
10869b1aec48SLars Fredriksen     return (1);
10879b1aec48SLars Fredriksen     }
10889b1aec48SLars Fredriksen 
10899b1aec48SLars Fredriksen int put_string (s)
10909b1aec48SLars Fredriksen register char *s;
10919b1aec48SLars Fredriksen     {
10929b1aec48SLars Fredriksen     s = clean(s, 1);
10939b1aec48SLars Fredriksen 
10949b1aec48SLars Fredriksen     if (verbose)
10959b1aec48SLars Fredriksen 	{
10969b1aec48SLars Fredriksen 	logf("send (");
10979b1aec48SLars Fredriksen 
10989b1aec48SLars Fredriksen 	if (quiet)
10999f65f104SPeter Wemm 	    {
11009b1aec48SLars Fredriksen 	    logf("??????");
11019f65f104SPeter Wemm 	    }
11029b1aec48SLars Fredriksen 	else
11039b1aec48SLars Fredriksen 	    {
11049b1aec48SLars Fredriksen 	    register char *s1 = s;
11059b1aec48SLars Fredriksen 
11069b1aec48SLars Fredriksen 	    for (s1 = s; *s1; ++s1)
11079f65f104SPeter Wemm 	        {
11089b1aec48SLars Fredriksen 		logf(character(*s1));
11099b1aec48SLars Fredriksen 	        }
11109f65f104SPeter Wemm 	    }
11119b1aec48SLars Fredriksen 
11129b1aec48SLars Fredriksen 	logf(")\n");
11139b1aec48SLars Fredriksen 	}
11149b1aec48SLars Fredriksen 
11159b1aec48SLars Fredriksen     alarm(timeout); alarmed = 0;
11169b1aec48SLars Fredriksen 
11179b1aec48SLars Fredriksen     while (*s)
11189b1aec48SLars Fredriksen 	{
11199b1aec48SLars Fredriksen 	register char c = *s++;
11209b1aec48SLars Fredriksen 
11219b1aec48SLars Fredriksen 	if (c != '\\')
11229b1aec48SLars Fredriksen 	    {
11239b1aec48SLars Fredriksen 	    if (!write_char (c))
11249f65f104SPeter Wemm 	        {
11259b1aec48SLars Fredriksen 		return 0;
11269f65f104SPeter Wemm 	        }
11279b1aec48SLars Fredriksen 	    continue;
11289b1aec48SLars Fredriksen 	    }
11299b1aec48SLars Fredriksen 
11309b1aec48SLars Fredriksen 	c = *s++;
11319b1aec48SLars Fredriksen 	switch (c)
11329b1aec48SLars Fredriksen 	    {
11339b1aec48SLars Fredriksen 	case 'd':
11349b1aec48SLars Fredriksen 	    sleep(1);
11359b1aec48SLars Fredriksen 	    break;
11369b1aec48SLars Fredriksen 
11379b1aec48SLars Fredriksen 	case 'K':
11389b1aec48SLars Fredriksen 	    break_sequence();
11399b1aec48SLars Fredriksen 	    break;
11409b1aec48SLars Fredriksen 
11419b1aec48SLars Fredriksen 	case 'p':
11429f65f104SPeter Wemm 	    usleep(10000); 	/* 1/100th of a second (arg is microseconds) */
11439b1aec48SLars Fredriksen 	    break;
11449b1aec48SLars Fredriksen 
11459b1aec48SLars Fredriksen 	default:
11469b1aec48SLars Fredriksen 	    if (!write_char (c))
11479b1aec48SLars Fredriksen 		return 0;
11489b1aec48SLars Fredriksen 	    break;
11499b1aec48SLars Fredriksen 	    }
11509b1aec48SLars Fredriksen 	}
11519b1aec48SLars Fredriksen 
11529b1aec48SLars Fredriksen     alarm(0);
11539b1aec48SLars Fredriksen     alarmed = 0;
11549b1aec48SLars Fredriksen     return (1);
11559b1aec48SLars Fredriksen     }
11569b1aec48SLars Fredriksen 
11579b1aec48SLars Fredriksen /*
11589b1aec48SLars Fredriksen  *	'Wait for' this string to appear on this file descriptor.
11599b1aec48SLars Fredriksen  */
11609b1aec48SLars Fredriksen int get_string(string)
11619b1aec48SLars Fredriksen register char *string;
11629b1aec48SLars Fredriksen     {
11639b1aec48SLars Fredriksen     char temp[STR_LEN];
11649b1aec48SLars Fredriksen     int c, printed = 0, len, minlen;
11659b1aec48SLars Fredriksen     register char *s = temp, *end = s + STR_LEN;
11669b1aec48SLars Fredriksen 
11679b1aec48SLars Fredriksen     fail_reason = (char *)0;
11689b1aec48SLars Fredriksen     string = clean(string, 0);
11699b1aec48SLars Fredriksen     len = strlen(string);
11709b1aec48SLars Fredriksen     minlen = (len > sizeof(fail_buffer)? len: sizeof(fail_buffer)) - 1;
11719b1aec48SLars Fredriksen 
11729b1aec48SLars Fredriksen     if (verbose)
11739b1aec48SLars Fredriksen 	{
11749b1aec48SLars Fredriksen 	register char *s1;
11759b1aec48SLars Fredriksen 
11769b1aec48SLars Fredriksen 	logf("expect (");
11779b1aec48SLars Fredriksen 
11789b1aec48SLars Fredriksen 	for (s1 = string; *s1; ++s1)
11799f65f104SPeter Wemm 	    {
11809b1aec48SLars Fredriksen 	    logf(character(*s1));
11819f65f104SPeter Wemm 	    }
11829b1aec48SLars Fredriksen 
11839b1aec48SLars Fredriksen 	logf(")\n");
11849b1aec48SLars Fredriksen 	}
11859b1aec48SLars Fredriksen 
11869b1aec48SLars Fredriksen     if (len > STR_LEN)
11879b1aec48SLars Fredriksen 	{
11889b1aec48SLars Fredriksen 	syslog(LOG_INFO, "expect string is too long");
11899f65f104SPeter Wemm 	exit_code = 1;
11909b1aec48SLars Fredriksen 	return 0;
11919b1aec48SLars Fredriksen 	}
11929b1aec48SLars Fredriksen 
11939b1aec48SLars Fredriksen     if (len == 0)
11949b1aec48SLars Fredriksen 	{
11959b1aec48SLars Fredriksen 	if (verbose)
11969b1aec48SLars Fredriksen 	    {
11979b1aec48SLars Fredriksen 	    syslog(LOG_INFO, "got it");
11989b1aec48SLars Fredriksen 	    }
11999b1aec48SLars Fredriksen 
12009b1aec48SLars Fredriksen 	return (1);
12019b1aec48SLars Fredriksen 	}
12029b1aec48SLars Fredriksen 
12039f65f104SPeter Wemm     alarm(timeout);
12049f65f104SPeter Wemm     alarmed = 0;
12059b1aec48SLars Fredriksen 
12069b1aec48SLars Fredriksen     while ( ! alarmed && (c = get_char()) >= 0)
12079b1aec48SLars Fredriksen 	{
12089f65f104SPeter Wemm 	int n, abort_len, report_len;
12099b1aec48SLars Fredriksen 
12109b1aec48SLars Fredriksen 	if (verbose)
12119b1aec48SLars Fredriksen 	    {
12129b1aec48SLars Fredriksen 	    if (c == '\n')
12139f65f104SPeter Wemm 	        {
12149b1aec48SLars Fredriksen 		logf("\n");
12159f65f104SPeter Wemm 	        }
12169b1aec48SLars Fredriksen 	    else
12179f65f104SPeter Wemm 	        {
12189b1aec48SLars Fredriksen 		logf(character(c));
12199b1aec48SLars Fredriksen 	        }
12209f65f104SPeter Wemm 	    }
12219b1aec48SLars Fredriksen 
12229b1aec48SLars Fredriksen 	*s++ = c;
12239b1aec48SLars Fredriksen 
12249b1aec48SLars Fredriksen 	if (s - temp >= len &&
12259b1aec48SLars Fredriksen 	    c == string[len - 1] &&
12269b1aec48SLars Fredriksen 	    strncmp(s - len, string, len) == 0)
12279b1aec48SLars Fredriksen 	    {
12289b1aec48SLars Fredriksen 	    if (verbose)
12299b1aec48SLars Fredriksen 		{
12309b1aec48SLars Fredriksen 		logf(" -- got it\n");
12319b1aec48SLars Fredriksen 		}
12329b1aec48SLars Fredriksen 
12339f65f104SPeter Wemm 	    alarm(0);
12349f65f104SPeter Wemm 	    alarmed = 0;
12359b1aec48SLars Fredriksen 	    return (1);
12369b1aec48SLars Fredriksen 	    }
12379b1aec48SLars Fredriksen 
12389b1aec48SLars Fredriksen 	for (n = 0; n < n_aborts; ++n)
12399f65f104SPeter Wemm 	    {
12409b1aec48SLars Fredriksen 	    if (s - temp >= (abort_len = strlen(abort_string[n])) &&
12419b1aec48SLars Fredriksen 		strncmp(s - abort_len, abort_string[n], abort_len) == 0)
12429b1aec48SLars Fredriksen 	        {
12439b1aec48SLars Fredriksen 		if (verbose)
12449b1aec48SLars Fredriksen 		    {
12459b1aec48SLars Fredriksen 		    logf(" -- failed\n");
12469b1aec48SLars Fredriksen 		    }
12479b1aec48SLars Fredriksen 
12489f65f104SPeter Wemm 		alarm(0);
12499f65f104SPeter Wemm 		alarmed = 0;
12509f65f104SPeter Wemm 		exit_code = n + 4;
12519b1aec48SLars Fredriksen 		strcpy(fail_reason = fail_buffer, abort_string[n]);
12529b1aec48SLars Fredriksen 		return (0);
12539b1aec48SLars Fredriksen 	        }
12549f65f104SPeter Wemm 	    }
12559f65f104SPeter Wemm 
12569f65f104SPeter Wemm 	if (!report_gathering)
12579f65f104SPeter Wemm 	    {
12589f65f104SPeter Wemm 	    for (n = 0; n < n_reports; ++n)
12599f65f104SPeter Wemm 	        {
12609f65f104SPeter Wemm 		if ((report_string[n] != (char*) NULL) &&
12619f65f104SPeter Wemm 		    s - temp >= (report_len = strlen(report_string[n])) &&
12629f65f104SPeter Wemm 		    strncmp(s - report_len, report_string[n], report_len) == 0)
12639f65f104SPeter Wemm 		    {
12649f65f104SPeter Wemm 		    time_t time_now   = time ((time_t*) NULL);
12659f65f104SPeter Wemm 		    struct tm* tm_now = localtime (&time_now);
12669f65f104SPeter Wemm 
12679f65f104SPeter Wemm 		    strftime (report_buffer, 20, "%b %d %H:%M:%S ", tm_now);
12689f65f104SPeter Wemm 		    strcat (report_buffer, report_string[n]);
12699f65f104SPeter Wemm 
12709f65f104SPeter Wemm 		    report_string[n] = (char *) NULL;
12719f65f104SPeter Wemm 		    report_gathering = 1;
12729f65f104SPeter Wemm 		    break;
12739f65f104SPeter Wemm 		    }
12749f65f104SPeter Wemm 	        }
12759f65f104SPeter Wemm 	    }
12769f65f104SPeter Wemm 	else
12779f65f104SPeter Wemm 	    {
12789f65f104SPeter Wemm 	    if (!iscntrl (c))
12799f65f104SPeter Wemm 	        {
12809f65f104SPeter Wemm 		int rep_len = strlen (report_buffer);
12819f65f104SPeter Wemm 		report_buffer[rep_len]     = c;
12829f65f104SPeter Wemm 		report_buffer[rep_len + 1] = '\0';
12839f65f104SPeter Wemm 	        }
12849f65f104SPeter Wemm 	    else
12859f65f104SPeter Wemm 	        {
12869f65f104SPeter Wemm 		report_gathering = 0;
12879f65f104SPeter Wemm 		fprintf (report_fp, "chat:  %s\n", report_buffer);
12889f65f104SPeter Wemm 	        }
12899f65f104SPeter Wemm 	    }
12909b1aec48SLars Fredriksen 
12919b1aec48SLars Fredriksen 	if (s >= end)
12929b1aec48SLars Fredriksen 	    {
12939b1aec48SLars Fredriksen 	    strncpy (temp, s - minlen, minlen);
12949b1aec48SLars Fredriksen 	    s = temp + minlen;
12959b1aec48SLars Fredriksen 	    }
12969b1aec48SLars Fredriksen 
12979b1aec48SLars Fredriksen 	if (alarmed && verbose)
12989f65f104SPeter Wemm 	    {
12999b1aec48SLars Fredriksen 	    syslog(LOG_WARNING, "warning: alarm synchronization problem");
13009b1aec48SLars Fredriksen 	    }
13019f65f104SPeter Wemm 	}
13029b1aec48SLars Fredriksen 
13039b1aec48SLars Fredriksen     alarm(0);
13049b1aec48SLars Fredriksen 
13059b1aec48SLars Fredriksen     if (verbose && printed)
13069b1aec48SLars Fredriksen 	{
13079b1aec48SLars Fredriksen 	if (alarmed)
13089f65f104SPeter Wemm 	    {
13099b1aec48SLars Fredriksen 	    logf(" -- read timed out\n");
13109f65f104SPeter Wemm 	    }
13119b1aec48SLars Fredriksen 	else
13129b1aec48SLars Fredriksen 	    {
13139b1aec48SLars Fredriksen 	    logflush();
13149b1aec48SLars Fredriksen 	    syslog(LOG_INFO, " -- read failed: %m");
13159b1aec48SLars Fredriksen 	    }
13169b1aec48SLars Fredriksen 	}
13179b1aec48SLars Fredriksen 
13189f65f104SPeter Wemm     exit_code = 3;
13199b1aec48SLars Fredriksen     alarmed   = 0;
13209b1aec48SLars Fredriksen     return (0);
13219b1aec48SLars Fredriksen     }
13229b1aec48SLars Fredriksen 
13239f65f104SPeter Wemm #ifdef NO_USLEEP
13249b1aec48SLars Fredriksen #include <sys/types.h>
13259b1aec48SLars Fredriksen #include <sys/time.h>
13269b1aec48SLars Fredriksen 
13279b1aec48SLars Fredriksen /*
13289b1aec48SLars Fredriksen   usleep -- support routine for 4.2BSD system call emulations
13299b1aec48SLars Fredriksen   last edit:  29-Oct-1984     D A Gwyn
13309b1aec48SLars Fredriksen   */
13319b1aec48SLars Fredriksen 
13329b1aec48SLars Fredriksen extern int	  select();
13339b1aec48SLars Fredriksen 
13349b1aec48SLars Fredriksen int
13359b1aec48SLars Fredriksen usleep( usec )				  /* returns 0 if ok, else -1 */
13369b1aec48SLars Fredriksen     long		usec;		/* delay in microseconds */
13379b1aec48SLars Fredriksen {
13389b1aec48SLars Fredriksen     static struct			/* `timeval' */
13399b1aec48SLars Fredriksen         {
13409b1aec48SLars Fredriksen 	long	tv_sec;		/* seconds */
13419b1aec48SLars Fredriksen 	long	tv_usec;	/* microsecs */
13429b1aec48SLars Fredriksen         } delay;	    /* _select() timeout */
13439b1aec48SLars Fredriksen 
13449b1aec48SLars Fredriksen     delay.tv_sec  = usec / 1000000L;
13459b1aec48SLars Fredriksen     delay.tv_usec = usec % 1000000L;
13469b1aec48SLars Fredriksen 
13479b1aec48SLars Fredriksen     return select( 0, (long *)0, (long *)0, (long *)0, &delay );
13489b1aec48SLars Fredriksen }
13499b1aec48SLars Fredriksen #endif
1350