/* * Changes for use with CM11A copyright 1996, 1997 - 2003 Daniel B. Suthers, * Pleasanton Ca, 94588 USA * E-mail dbs@tanj.com * Subject to the same permissions and restrictions as below. */ /* * Copyright 1986 by Larry Campbell, 73 Concord Street, Maynard MA 01754 USA * (maynard!campbell). You may freely copy, use, and distribute this software * subject to the following restrictions: * * 1) You may not charge money for it. * 2) You may not remove or alter this copyright notice. * 3) You may not claim you wrote it. * 4) If you make improvements (or other changes), you are requested * to send them to me, so there's a focal point for distributing * improved versions. * * John Chmielewski (tesla!jlc until 9/1/86, then rogue!jlc) assisted * by doing the System V port and adding some nice features. Thanks! */ #include #include #include #if (defined(SCO) || defined (SOLARIS)) #include #else #include #endif #include #include #include "x10.h" #if (defined(LINUX) || defined(SOLARIS) || defined(FREEBSD)) #include /* char *strerror(); */ #endif extern int verbose; extern int i_am_relay; unsigned alarm(); void sigtimer(); #ifdef HAS_ITIMER #include #include struct itimerval iold, icurrent; #endif /* * xread(fd, buf, count, timeout) * * Timed read. Works just like read(2) but gives up after * timeout seconds, returning whatever's been read so far. */ /* NOTE: The CM11A will pop out a poll message every second when it wants * to send an update. Alarm(1) will go off when the next second starts. * This may be any amount of time up to 1 second. This makes a normal * alarm(1) unsuitable. Thus the use of setitimer. Other OSes will have * similar capabilities that assure a 1 second alarm is actually one second. */ jmp_buf jb; int xread(fd, buf, count, timeout) int fd, count, timeout; unsigned char *buf; { static int total; /* so setjump won't clobber it */ extern int i_am_relay; int counter; char * cbuf; char RCSID[]= "@(#) $Id: xread.c,v 1.10 2003/03/17 01:40:32 dbs Exp dbs $\n"; display(RCSID); if (verbose && (! i_am_relay) ) fprintf(stderr, "xread() called, count=%d, timeout = %d\n", count, timeout); total = 0; if (setjmp(jb)) { if (verbose && (! i_am_relay) ) fprintf(stderr, "xread() returning %d after timeout\n", total); (void) alarm(0); (void) signal(SIGALRM, SIG_IGN); return (total); } /* The compiler would complain that * "argument `buf' and count might be clobbered by `longjmp'" * This is bacause we change them after the setjmp. * To prevent this, we use copies of the arguements. */ cbuf = buf; counter = count; (void)alarm(0); (void) signal(SIGALRM, sigtimer); #ifdef HAS_ITIMER icurrent.it_interval.tv_sec = 0; icurrent.it_interval.tv_usec = 0; icurrent.it_value.tv_sec = timeout; icurrent.it_value.tv_usec = 30; if (setitimer(ITIMER_REAL, &icurrent, &iold) == -1) if( !i_am_relay ) perror ("setitimer"); #else (void) alarm((unsigned) timeout); #endif errno = 0; while (counter--) { /* loop till all charaters are read */ int i; if ((i = read(fd, (char *) cbuf, 1)) < 1) { if (i == 0) { /* loop around on EOF */ counter++; /* reverse the decrement in the while loop. */ if( errno == EINTR) /* alarm was triggered */ { break; } continue; } if( (i < 0) && (i_am_relay != 1) ) perror("read"); else if( (i < 0) && (i_am_relay == 1) ) { syslog(LOG_ERR,"Relay Xread read error"); syslog(LOG_ERR, strerror(errno)); } (void) alarm(0); (void) signal(SIGALRM, SIG_IGN); if (verbose) fprintf(stderr, "xread() returning %d after error\n", total); return (total); } cbuf++; total++; } (void) alarm(0); (void) signal(SIGALRM, SIG_IGN); if (verbose && (i_am_relay != 1) ) fprintf(stderr, "xread() returning %d byte(s). The first is %x\n", total, buf[0] ); return (total); } void sigtimer() { if (verbose && (! i_am_relay) ){ fprintf(stderr, "Alarm!\n"); fflush(stderr); } (void) signal(SIGALRM, sigtimer); errno = EINTR; return; /* the jmp temporarily disabled (version 1.34) ... It was causing problems when triggered under linux 2.2.20 using USB. The second trap would not behave properly. I don't know why. */ /* longjmp(jb, 1); */ } /* expect xread sends a code to the spool file that specifys how many * incoming characters are to be discarded. * The code is 3 0xff followed by (the number of bytes to expect +127) */ int exread(fd, buf, count, timeout) int fd; char *buf; int count; int timeout; { char lbuf[160]; extern int sptty; lbuf[1] = lbuf[2] = lbuf[0] = 0xff; lbuf[3] = count+127; if( (! i_am_relay ) && write( sptty, lbuf , 4) != 4) { /* if( i_am_relay ) { syslog (LOG_ERR, "exread(): write failed\n"); } else */ { fprintf (stderr, "exread(): write failed\n"); } } return(xread( fd, buf, count, timeout)); }