From daryl@tcomeng.com Mon Mar 27 11:15:21 1995 Return-Path: daryl@tcomeng.com Received: from tcomeng.com (tcomeng.tcomeng.com [165.113.239.100]) by locust.net.ohio-state.edu (8.6.10/8.6.9) with SMTP id LAA06199 for ; Mon, 27 Mar 1995 11:15:19 -0500 Received: by tcomeng.com id AA36722 (5.67a/IDA-1.5 for maf@net.ohio-state.edu); Mon, 27 Mar 1995 08:14:48 -0800 From: Daryl Jones Message-Id: <199503271614.AA36722@tcomeng.com> Subject: Re: sendpage To: maf@net.ohio-state.edu Date: Mon, 27 Mar 1995 08:14:47 -0800 (PST) In-Reply-To: <199503271611.LAA00669@bedbugs.net.ohio-state.edu> from "Mark A. Fullmer" at Mar 27, 95 11:11:37 am X-Mailer: ELM [version 2.4 PL24] Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Length: 1450 Status: RO Mark: Sendpage is working great now... I had to add some code in signal.c to reset the signal handler each time a signal is processed. Otherwise, sendpage would about on the 2nd time the alarm() timer went off. Does this make sense to you? Daryl ============================================================================ /***************************************************************************/ /* Module: $Id: signal.c,v 1.1 1995/01/10 01:44:35 maf Exp $ /* Description: signal handling code for sendpage /* Author: maf /* Copyright (c) 1995 Mark Fullmer and The Ohio State University /***************************************************************************/ /* $Log: signal.c,v $ * Revision 1.1 1995/01/10 01:44:35 maf * Initial revision * * Revision 1.1 1995/01/10 01:44:35 maf * Initial revision * */ #include #include sig_hup(sig) int sig; { extern int need_readconfig; need_readconfig = 1; signal(SIGHUP, sig_hup); /* ddj */ } sig_usr1(sig) int sig; { extern int need_runqueue; need_runqueue = 1; signal(SIGUSR1, sig_usr1); /* ddj */ } sig_alrm(sig) int sig; { extern int need_runqueue; need_runqueue = 1; signal(SIGALRM, sig_alrm); /* ddj */ } sig_quit(sig) int sig; { extern int need_quit; need_quit = 1; signal(SIGQUIT, sig_quit); /* ddj */ } sig_pipe(sig) int sig; { extern int got_sigpipe; got_sigpipe = 1; signal(SIGPIPE, sig_pipe); } From daryl@tcomeng.com Mon Mar 27 13:37:34 1995 Return-Path: daryl@tcomeng.com Received: from phem6.acs.ohio-state.edu (osu.edu [128.146.225.200]) by locust.net.ohio-state.edu (8.6.10/8.6.9) with SMTP id NAA06608 for ; Mon, 27 Mar 1995 13:37:32 -0500 Received: from fuzz-e-mail by phem6.acs.ohio-state.edu; Mon, 27 Mar 95 13:36 EST Received: from tcomeng.com (tcomeng.tcomeng.com) by phem6.acs.ohio-state.edu; Mon, 27 Mar 95 13:36 EST Received: by tcomeng.com id AA42587 (5.67a/IDA-1.5 for maf+@osu.edu); Mon, 27 Mar 1995 10:36:12 -0800 Date: Mon, 27 Mar 1995 10:36:12 -0800 (PST) From: Daryl Jones Subject: io.c To: maf+@osu.edu Message-id: <199503271836.AA42587@tcomeng.com> X-Mailer: ELM [version 2.4 PL24] Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Length: 26378 X-Envelope-to: maf@net.ohio-state.edu Status: RO Mark: Here's what we had to do to io.c to make it work on AIX... /***************************************************************************/ /* Module: $Id: io.c,v 1.2 1995/03/15 04:40:53 maf Exp $ /* Description: Lower level io for PET protocol and modem /* Author: maf /* /* Copyright (c) 1995 Mark Fullmer and The Ohio State University /***************************************************************************/ /* $Log: io.c,v $ * Revision 1.2 1995/03/15 04:40:53 maf * *** empty log message *** * * Revision 1.1 1995/01/10 01:43:05 maf * Initial revision * * Revision X.X 1995/03/25 05:30:00 mark@tcomeng.com * Support for Risc/6000 AIX 3.2.5 * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "report.h" #include "sendpage.h" #ifdef NEED_MALLOC_H #include #endif /*********************************************************************/ /* Function: OpenModem /* /* Returns: 0 for good (the device was opened and initialized) /* !0 for bad /* /*********************************************************************/ OpenModem(pcinfo, fd) struct pcinfo *pcinfo; int *fd; { extern int errno, debug; struct termios t; struct cbuf cb; #ifdef DEBUG if (debug > 2) report (LOG_INFO, "opening modem"); #endif /* DEBUG */ /* open the modem device */ if ((*fd = open (pcinfo->modemdev, O_RDWR | O_NDELAY, 0)) == -1) { report(LOG_ERR, "open (%s): %s", pcinfo->modemdev, strerror(errno)); return 1; /* bad */ } /* setup the device (baud rate, etc) */ /* get the current device params */ if (tcgetattr(*fd, &t)) { report (LOG_ERR, "tcgetattr (modem): %s", strerror(errno)); close (*fd); return 1; } /* input flags : /* ignore breaks, use XON/XOFF flow control /* ignore parity errors */ t.c_iflag = IGNBRK|IXON|IXOFF|IGNPAR; /* strip the 8th bit if not on 8 bit mode */ if (pcinfo->databits != CS8) t.c_iflag |= ISTRIP; /* output flags: /* (none) */ t.c_oflag = 0; /* hardware control flags: /* enable receiver, modem control lines go low on close(), use RTS/CTS (hardwire) flow control to modem */ t.c_cflag=0; t.c_cflag = pcinfo->speed|pcinfo->databits|pcinfo->parity|pcinfo->stopbits| CLOCAL|HUPCL|CREAD; /* local flags: /* (none) */ t.c_lflag = 0; /* allow read() to return 0 bytes (ie don't block), accept wait atleast */ /* one second before returning 0 bytes */ t.c_cc[VMIN] = 0; t.c_cc[VTIME] = 10000; /* 1/10ths of seconds */ /* set device params */ /*if (ioctl(*fd, TCSETA, &t))*/ if (tcsetattr(*fd, TCSANOW, &t)) { report (LOG_ERR, "tcsetattr (modem): %s", strerror(errno)); close (*fd); return 1; /* bad */ } SendBytes(*fd,"AT\r",3); return 0; /* good */ } /* OpenModem */ /*********************************************************************/ /* Function: ResetModem /* /* Returns: 0 for good (the device was reset and is responding) /* !0 for bad /* /*********************************************************************/ ResetModem(fd, cbuf, pcinfo) int fd; struct cbuf *cbuf; struct pcinfo *pcinfo; { extern int errno, debug; int modem; /* printf("Start Pager\n"); */ #ifdef MARK /* first toggle DTR - some modems will go to command state when doing this */ /* get the current modem control lines */ if (ioctl(fd, TIOCMGET, &modem) == -1) { report (LOG_ERR, "ioctl (modem, TIOMGET): %s", strerror(errno)); return 1; /* bad */ } /* turn off DTR */ modem &= ~TIOCM_DTR; sleep (1); /* tell the modem */ if (ioctl(fd, TIOCMSET, &modem) == -1) { report (LOG_ERR, "ioctl (modem, TIOCMSET): %s", strerror(errno)); return 1; /* bad */ } sleep (1); modem |= TIOCM_DTR; /* tell the modem */ if (ioctl(fd, TIOCMSET, &modem) == -1) { report (LOG_ERR, "ioctl (modem, TIOCMSET): %s", strerror(errno)); return 1; /* bad */ } /* give the modem a chance to recover */ sleep (1); /* now send the +++ wait ath */ if (SendString (fd, " ")) return 1; sleep (2); #endif if (SendString(fd, MODEM_PLUS)) return 1; sleep (3); if (SendString (fd, "\r")) return 1; /* depending on the previous state of the modem, different things could show up here - OK\r or the short number command for OK or whatever else some goofy clone decided to do. Forget the return code here, instead just go ahead and send the init command */ sleep (1); if (SendString(fd, pcinfo->modeminit)) return 1; sleep(1); if (SendString(fd, "\r")) return 1; /* Now wait for the OK short result code */ if (WaitString(fd, "0\r", cbuf)) return 1; /* the previous result code could of been from a few sources */ /* sync up us to the modem by setting the return code to the word /* form, then the number form */ SendString (fd, MODEM_WORDS); /* should get an OK\r */ sleep(1); WaitString (fd, MODEM_WORD_OK, cbuf); SendString (fd, MODEM_WORDS); /* should get an OK\r */ sleep(1); if (WaitString (fd, MODEM_WORD_OK, cbuf)) return 1; if (SendString (fd, MODEM_NUMS)) return 1; if (WaitString(fd, "\n", cbuf)) return 1; /* that's it */ return 0; /* good */ } /* Reset Modem */ /*********************************************************************/ /* Function: SendString /* /* Returns: 0 for good (string was sent) /* !0 for bad /* /*********************************************************************/ SendString (fd, string) int fd; char *string; { return SendBytes (fd, string, strlen(string)); } /* SendString */ /*********************************************************************/ /* Function: WaitString /* /* Returns: 0 for good (string was received) /* !0 for bad /* /* It's assumed the fd is setup so that a read() will block for atleast /* 1 second before returning 0 bytes. /* /*********************************************************************/ WaitString (fd, msg, cbuf) int fd; char *msg; struct cbuf *cbuf; { int msglen, goodbytes, x, n, retries, retries2, matchflag; extern int errno, debug; msglen = strlen(msg); retries = 5; /* try the loop 5 times */ retries2 = 150; /* inner loop 50 times (just a safety) */ goodbytes = 0; /* no bytes matched yet */ matchflag = 0; /* no full match of msg */ #ifdef DEBUG if (debug > 2) report (LOG_INFO, "WaitString (%d bytes) - %s", msglen, PrintBytes (msg, msglen)); #endif /* DEBUG */ /* try retries times to read when there is nothing to read */ /* if there was something to read, then retries2 also gets counted */ for (; (retries > 0) && (!matchflag); --retries) { #ifdef DEBUG if (debug > 2) report (LOG_INFO, "retry = %d", retries); #endif /* DEBUG */ if ((n = SafeRead(fd, cbuf->buf+cbuf->bufused, CBUF_BYTES - cbuf->bufused)) == -1) return 1; cbuf->bufused += n; #ifdef DEBUG if (debug > 2) report (LOG_INFO, "cbuf (%d bytes) - %s", cbuf->bufused, PrintBytes (cbuf->buf, cbuf->bufused)); #endif /* try to match */ for (x = goodbytes; x < cbuf->bufused; ++x) { /* if the byte doesn't match, discard the previous bytes that matched, else setup to try next */ if (msg[goodbytes] != cbuf->buf[x]) goodbytes = 0; else ++goodbytes; if (goodbytes == msglen) { /* full match */ matchflag = 1; ++x; break; } } /* for x */ #ifdef DEBUG if (debug > 2) report (LOG_INFO, "matchflag=%d, x=%d, bufused=%d, goodbytes=%d msglen=%d", matchflag, x, cbuf->bufused, goodbytes, msglen); #endif /* DEBUG */ /* save the end of the buffer that didn't match for next time */ if (matchflag) { bcopy(cbuf->buf+x, cbuf->buf, cbuf->bufused-x); cbuf->bufused -= x; } else { bcopy(cbuf->buf+(x-goodbytes), cbuf->buf, goodbytes); cbuf->bufused = goodbytes; } /* give the device some time to talk */ if (!matchflag && !n) sleep (1); /* if bytes were actually read, keep trying a little longer */ if (n && retries2) -- retries2, ++retries; } /* for retries */ #ifdef DEBUG if (debug > 2) report (LOG_INFO, "%smatch", matchflag ? "" : "no" ); #endif /* DEBUG */ return (matchflag) ? 0 : 1; } /* WaitString */ /*********************************************************************/ /* Function: SafeRead /* /* Execute read with check and log /* Returns -1 for error. /* /* /*********************************************************************/ SafeRead (fd, buf, len) int fd; char *buf; int len; { int n; if ((n = read(fd, buf, len)) == -1) { report (LOG_ERR, "read(): %s", strerror(errno)); return -1; } return n; } /*********************************************************************/ /* Function: PrintBytes /* /* Returns: pointer to upto 132 chars of string /* /* /*********************************************************************/ #ifdef DEBUG char *PrintBytes (buf, len) char *buf; int len; { static char tmpBuf[132]; char s[10], *c; int x; for (c = buf, x = 0; c != (buf + len); ++c) { if (isalnum((int)*c)) { if (x <= 129) { tmpBuf[x++] = *c; tmpBuf[x++] = ' '; } /* if */ else break; } /* if */ else { if (x <= 128) { sprintf(s, "%2.2x ", (int)*c); bcopy(s, &tmpBuf[x], 3); x += 3; } /* if */ else break; } /* else */ } /* for */ tmpBuf[x] = 0; return tmpBuf; } /* PrintBytes */ #endif /* DEBUG */ /*********************************************************************/ /* Function: DialModem /* /* Returns: MODEM_RES_?? constants /* /*********************************************************************/ DialModem(fd, cbuf, pcinfo) int fd; struct cbuf *cbuf; struct pcinfo *pcinfo; { extern int errno, debug; int x, res=0; char dialstring[PCINFO_STR_LEN*2+1]; SendString (fd, "\rAT\r"); strcpy(dialstring, pcinfo->modemdial); strcat(dialstring, pcinfo->phone); strcat(dialstring, "\r"); sleep(2); /* ddj for tcomeng and Codex modems */ if (SendString (fd, dialstring)) return MODEM_RES_INTER; /* GetResult in cbuf */ while (!res || res>50) { cbuf->bufused=0; if (WaitLine (fd, cbuf, 60)) return MODEM_RES_INTER; /* parse and return the result */ /* convert to int, then discard */ for (x = 0; x < cbuf->bufused; ++x) { if (cbuf->buf[x] == 0x0d) { cbuf->buf[x] = 0; break; } } /* for */ res = atoi(cbuf->buf); /* discard what just got picked off */ bcopy(cbuf->buf+x, cbuf->buf, cbuf->bufused-x); cbuf->bufused -= x; } return res; } /* DialModem */ /*********************************************************************/ /* Function: WaitLine /* /* Returns: 0 for good (a line (string ending in 0x0d) was received) /* !0 for bad /* /*********************************************************************/ WaitLine (fd, cbuf, retries) int fd; struct cbuf *cbuf; int retries; { int x, n, retries2, matchflag; extern int errno, debug; retries2 = 50; /* inner loop 50 times (just a safety) */ matchflag = 0; /* got a line */ /* try retries times to read when there is nothing to read */ /* if there was something to read, then retries2 also gets counted */ for (; (retries > 0) && (!matchflag); --retries) { #ifdef DEBUG if (debug > 2) report (LOG_INFO, "retry = %d", retries); #endif /* DEBUG */ if ((n = SafeRead(fd, cbuf->buf+cbuf->bufused, CBUF_BYTES - cbuf->bufused)) == -1) return 1; cbuf->bufused += n; #ifdef DEBUG if (debug > 2) report (LOG_INFO, "cbuf n=%d (%d bytes) - %s", n,cbuf->bufused, PrintBytes (cbuf->buf, cbuf->bufused)); #endif /* try to match */ for (x = 0; x < cbuf->bufused; ++x) { if (cbuf->buf[x] == 0x0d) { matchflag = 1; break; } } /* for x */ /* give the device some time to talk */ if (!matchflag && !n) sleep (1); /* if bytes were actually read, keep trying a little longer */ if (n && retries2) -- retries2, ++retries; } /* for retries */ return (matchflag) ? 0 : 1; } /* WaitLine */ /*********************************************************************/ /* Function: StartPET /* /* Returns: 0 for good (The logon sequence succeeded) /* 1 for bad /* /*********************************************************************/ StartPET(fd, cbuf, pcinfo) int fd; struct cbuf *cbuf; struct pcinfo *pcinfo; { extern int errno, debug; int retrystart, retrylogin, gotid, gotlogin, res, earlygoahead; char passwd[8]; char *prot; gotid = 0; /* got the PET_ID */ gotlogin = 0; /* got through the login sequence */ retrystart = 3; /* number of times to try for PET_ID */ retrylogin = 3; /* number of times to try for */ earlygoahead = 0; /* got an early go ahead message */ /* construct password line */ sprintf(passwd, "%s\r",pcinfo->password); /* Protocol requires 3 retries of sending CR, waiting for ID= */ while (--retrystart >= 0) { if (SendString (fd, "\r")) return 1; /* bad */ if (!WaitString (fd, PET_ID, cbuf)) { gotid = 1; break; } } if (!gotid) { report (LOG_ERR, "Never got %s (initial logon sequence)", PET_ID); return 1; /* bad */ } while (--retrylogin >= 0) { /* put remote side into automatic remote entry mode */ if (pcinfo->protocol == PC_PET1) prot = PET_START_SEQ1; else if (pcinfo->protocol == PC_PET3) prot = PET_START_SEQ3; else prot = ""; if (SendString (fd, prot)) return 1; /* bad */ /* send the password followrd by 0x0d */ if (SendString (fd, passwd)) return 1; /* bad */ /* at this point, paging central can do a few things */ /* 1) reply with ID= meaning send the PET_START_SEQ/passwd again /* 2) reply with meaning ok, go ahead /* 3) reply with meaning try again /* 4) reply with meaning get lost /* 5) reply with something else, meaning who knows what */ /* The ID= response is problematic, since it could of been an ID= /* that previously wasn't read. For this reason, the ID= response /* is handled as case 5 (ie 2,3,4 weren't matched), and things /* start over with the PET_START_SEQ upto retrylogin times */ /* Wait for a PET reply */ res = WaitPETReply (fd, cbuf); /* accept PET_REPLY_ACCEPT */ if (res == PET_REPLY_ACCEPT) { gotlogin = 1; break; } /* my spec says this is wrong, ofcourse that means nothing when /* paging central goes ahead and does it anyways */ if (res == PET_REPLY_GOAHEAD) { gotlogin = 1; earlygoahead = 1; break; } report (LOG_INFO, "Unexpected reply during login, retrying - %d", res); } /* while retrylogin */ if (!gotlogin) { report (LOG_ERR, "Never got through login sequence - reason %d", res); return 1; /* bad */ } /* wait for PET_GOAHEAD message */ if (!earlygoahead) { res = WaitPETReply (fd, cbuf); if (res != PET_REPLY_GOAHEAD) { report (LOG_ERR, "Never got go ahead message - reason %d", res); return 1; /* bad */ } } return 0; /* good */ } /* StartPET */ /*********************************************************************/ /* Function: WaitPETReply /* /* Returns: PET_REPLY_?? /* /*********************************************************************/ WaitPETReply (fd, cbuf) int fd; struct cbuf *cbuf; { int x, n, retries, retries2, pet, matchflag, goodbytes, j; extern int errno, debug; int pet_goodbytes[PET_REPLIES]; extern struct pet_lookup petlookup[]; retries = 10; /* upto 10 seconds of idle time per protocol spec */ retries2 = 50; /* 50 times (just a safety) */ matchflag = 0; goodbytes = 0; for (pet = 0; pet < PET_REPLIES; ++pet) pet_goodbytes[pet] = 0; /* try retries times to read when there is nothing to read */ /* if there was something to read, then retries2 also gets counted */ for (; (retries > 0) && (!matchflag); --retries) { #ifdef DEBUG if (debug > 2) report (LOG_INFO, "retry = %d", retries); #endif /* DEBUG */ if ((n = SafeRead(fd, cbuf->buf+cbuf->bufused, CBUF_BYTES - cbuf->bufused)) == -1) return 1; cbuf->bufused += n; #ifdef DEBUG if (debug > 2) report (LOG_INFO, "cbuf (%d bytes) - %s", cbuf->bufused, PrintBytes (cbuf->buf, cbuf->bufused)); #endif /* try to match PET_REPLY_?? */ for (x = goodbytes; x < cbuf->bufused; ++x) { /* protocol allows optional linefeeds after carriage returns - just ignore them all. */ if (cbuf->buf[x] == ASCII_LF) continue; for (pet = 0; pet < PET_REPLIES; ++pet) { if (cbuf->buf[x] != pet_lookup[pet].msg[pet_goodbytes[pet]]) pet_goodbytes[pet] = 0; else ++pet_goodbytes[pet]; if (pet_goodbytes[pet] == pet_lookup[pet].msglen) { matchflag = 1; ++x; break; } /* if */ #ifdef DEBUG if (debug > 2) report (LOG_INFO, "pet=%d, matchflag=%d, pet_lookup[].msglen=%d, pet_goodbytes[]=%d", pet, matchflag, pet_lookup[pet].msglen, pet_goodbytes[pet]); #endif /* DEBUG */ } /* for pet */ if (matchflag) break; } /* for x */ /* calculate the max # of bytes in this buf to save */ for (j = 0, goodbytes = 0; j < PET_REPLIES; ++j) if (pet_goodbytes[j] > goodbytes) goodbytes = pet_goodbytes[j]; #ifdef DEBUG if (debug > 2) report (LOG_INFO, "matchflag=%d, x=%d, bufused=%d, goodbytes=%d pet=%d", matchflag, x, cbuf->bufused, goodbytes, pet); #endif /* DEBUG */ /* save the end of the buffer that didn't match for next time */ if (matchflag) { bcopy(cbuf->buf+x, cbuf->buf, cbuf->bufused-x); cbuf->bufused -= x; } else { bcopy(cbuf->buf+(x-goodbytes), cbuf->buf, goodbytes); cbuf->bufused = goodbytes; } #ifdef DEBUG if (debug > 2) report (LOG_INFO, "after bcopy buf (%d bytes) - %s", cbuf->bufused, PrintBytes (cbuf->buf, cbuf->bufused)); #endif /* DEBUG */ /* give the device some time to talk */ if (!matchflag && !n) sleep (1); /* if bytes were actually read, keep trying a little longer */ if (n && retries2) -- retries2, ++retries; } /* for retries */ return (matchflag) ? pet : PET_ERROR; } /* WaitPETReply */ /*********************************************************************/ /* Function: SendPETTransaction /* /* Returns: 0 for good (the transaction was accepted) /* 1 for bad (some kind of error that should be retried) /* 2 for bad (page rejected) /* 3 for bad (all pages rejected) /* /*********************************************************************/ SendPETTransaction(fd, cbuf, field1, field2, protocol) int fd; struct cbuf *cbuf; char *field1, *field2; { extern int errno, debug; int retries, goodsend; char pet_packet [256]; int pet_len, res, pagereject, abandon; pet_len = 256; retries = 3; goodsend = 0; pagereject = 0; abandon = 0; /* create the pet_packet */ if (MakePETPacket(pet_packet, &pet_len, field1, field2, protocol)) return 1; while ((--retries >= 0) && (!goodsend)) { if (SendBytes (fd, pet_packet, pet_len)) return 1; res = WaitPETReply (fd, cbuf); switch (res) { case PET_REPLY_ACCEPT: report (LOG_INFO, "packet accepted"); goodsend = 1; break; case PET_REPLY_REJECT: report (LOG_WARNING, "packet rejected, retrying"); pagereject = 1; break; case PET_REPLY_ABANDON: report (LOG_ERR, "abandon packet, giving up"); abandon = 1; retries = 0; break; case PET_REPLY_GOODBYE: report (LOG_ERR, "goodby after transaction -- did it send?"); retries = 0; break; default: report (LOG_ERR, "unexpected response from WaitPETReply - %d", res); break; } /* switch */ } /* while --retries */ #ifdef DEBUG if (debug > 2) report (LOG_INFO, "SendPETTransaction exiting with goodsend=%d", goodsend); #endif /* DEBUG */ if (goodsend) return 0; else if (abandon) return 3; else if (pagereject) return 2; else return 1; } /* SendPETTransaction */ /*********************************************************************/ /* Function: MakePETPacket /* /* Returns: 0 for good (the packet was successfully constructed) /* 1 for bad /* /*********************************************************************/ MakePETPacket(buf, buflen, field1, field2, protocol) char *buf, *field1, *field2; int *buflen; int protocol; { int len1, len2, x, i; int csum; char *p; len1 = strlen(field1); len2 = strlen(field2); csum = 0; if ((len1 + len2 + 8) > *buflen) return 1; /* start with a STX */ buf[0] = ASCII_STX; i = 1; /* add field 1 */ bcopy(field1, &buf[i], len1); i += len1; /* field 1 ends with CR */ buf[i] = ASCII_CR; ++i; /* add field 2 */ bcopy(field2, &buf[i], len2); i += len2; /* field 2 ends with CR */ buf[i] = ASCII_CR; ++i; /* if the protocol is PC_PET3 need to add CR again for destination */ if (protocol == PC_PET3) buf[i++] = ASCII_CR; /* end fields with ETX */ buf[i] = ASCII_ETX; ++i; /* 7 bit checksum follows */ for (x = 0; x < i; ++x) csum += (buf[x] & 0x7f); /* the checksum is represented as 3 ascii characters having the values between 0x30 and 0x3f */ /* tack it on backwards */ buf[i+2] = 0x30 + (csum & 0x0f); csum >>= 4; buf[i+1] = 0x30 + (csum & 0x0f); csum >>= 4; buf[i] = 0x30 + (csum & 0x0f); /* end it all with a CR */ buf[i+3] = ASCII_CR; *buflen = i+4; return 0; } /* MakePETPacket /*********************************************************************/ /* Function: SendBytes /* /* Returns: 0 for good (bytes were sent) /* !0 for bad /* /*********************************************************************/ SendBytes (fd, bytes, len) int fd; char *bytes; int len; { extern int errno, debug; #ifdef DEBUG if (debug > 2) report (LOG_INFO, "SendBytes (%d bytes) - %s", len, PrintBytes (bytes, len)); #endif /* DEBUG */ if (write (fd, bytes, len) == -1) { report(LOG_ERR, "write(): %s", strerror(errno)); perror("XX"); return 1; /* bad */ } return 0; /* good */ } /* SendBytes */ /*********************************************************************/ /* Function: EndPETTransaction /* /* Returns: 0 for good the (transaction was ended) /* 1 for bad (unknown state) /* 2 got ABANDON packet (this invalidates all previous transactions) /* /*********************************************************************/ EndPETTransaction(fd, cbuf) int fd; struct cbuf *cbuf; { extern int errno, debug; int res; if (SendString (fd, PET_END_SEQ)) return 1; res = WaitPETReply(fd, cbuf); if (res == PET_REPLY_ABANDON) return 2; if (res == PET_REPLY_GOODBYE) return 0; /* be liberal on what we accept...*/ report (LOG_WARNING, "unexpected termination reply %d", res); return 0; } /* EndPETTransaction */ #ifdef UUCP_LOCKING /*********************************************************************/ /* Function: LockTTY /* /* Returns: 1 don't have lock /* 0 got lock /* /* error reporting done via report() /* /*********************************************************************/ LockTTY(ttyname) char *ttyname; { char lockfile[_POSIX_PATH_MAX], tmpfile[_POSIX_PATH_MAX]; char *tty; int fd, unlocked, isrunning; pid_t pid, pid2; char cpid[12]; /* 32 bits is 10 chars max + \n + terminator */ FILE *FP; unlocked = 1; /* don't have lock */ fd = -1; /* point to the last component of the pathname for the tty */ if ((tty = strrchr(ttyname, '/'))) ++tty; else tty = ttyname; pid = getpid(); /* create a temp file and lock file pathnames */ sprintf(tmpfile, "%sLTMP.%u", TTY_LOCKDIR, (u_int)pid); sprintf(lockfile, "%sLCK..%s", TTY_LOCKDIR, tty); /* make sure there's not an extra one laying around */ unlink(tmpfile); /* create the temp file */ if ((fd = open(tmpfile, O_WRONLY|O_CREAT|O_EXCL, 0444)) == -1) { report(LOG_ERR, "open(%s): %s", tmpfile, strerror(errno)); goto LockTTYout; } sprintf(cpid, "%u\n", (u_int)pid); /* stick our pid in the file */ if (write(fd, cpid, strlen(cpid)) == -1) { report(LOG_ERR, "write(%s): %s", tmpfile, strerror(errno)); goto LockTTYout; } if (close(fd) == -1) { fd = -1; goto LockTTYout; } fd = -1; /* try to link our temp file to the real one */ if (!link(tmpfile, lockfile)) { unlocked = 0; goto LockTTYout1; /* good */ } /* couldn't get the lock, but all is not lost. The lockfile has a process id in it, Maybe that process died an untimely death and couldn't cleanup after itself */ isrunning = 1; if ((FP = fopen(lockfile, "r"))) { fscanf(FP, "%lu", &pid2); fclose(FP); if ((pid2) && (kill((int)pid2, 0))) isrunning = 0; } if (!isrunning) { report(LOG_INFO, "ignoring stale lock file: %s", lockfile); unlink(lockfile); if (!link(tmpfile, lockfile)) { unlocked = 0; goto LockTTYout1; /* good */ } report(LOG_ERR, "ignore lock file failed"); } LockTTYout1: /* remove the temp file */ if (unlink(tmpfile) == -1) report(LOG_WARNING, "unlink(%s): %s", tmpfile, strerror(errno)); LockTTYout: if (fd != -1) close (fd); return unlocked; } /* LockTTY */ /*********************************************************************/ /* Function: UnLockTTY /* /* Returns: 0 removed lock /* 1 couldn't remove lock /* /* error reporting done via report() /* /*********************************************************************/ UnLockTTY(ttyname) char *ttyname; { char lockfile[_POSIX_PATH_MAX]; char *tty; /* point to the last component of the pathname for the tty */ if ((tty = strrchr(ttyname, '/'))) ++tty; else tty = ttyname; sprintf(lockfile, "%sLCK..%s", TTY_LOCKDIR, tty); if (unlink(lockfile) == -1) { report (LOG_ERR, "can't remove lock for %s", tty); return 1; /* bad */ } return 0; /* good */ } /* UnLockTTY */ #endif /* UUCP_LOCKING /*********************************************************************/ /* Function: HangUpModem /* /* Returns: 0 for good - it was able to send the modem hangup comand /* and get a response. /* !0 for bad /* /*********************************************************************/ HangUpModem(fd, cbuf) int fd; struct cbuf *cbuf; { /* give the modem a chance to recover */ sleep (1); /* now send the +++ wait ath */ if (SendString (fd, " ")) return 1; sleep (2); if (SendString(fd, MODEM_PLUS)) return 1; sleep (3); if (SendString (fd, "\r")) return 1; /* Now wait for the OK short result code */ if (WaitString(fd, "\r", cbuf)) return 1; return 0; }