home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Telecom
/
1996-04-telecom-walnutcreek.iso
/
technical
/
ixo.program.scripts
/
ixocico.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-14
|
13KB
|
581 lines
/* ixocico -- IXO protocol call-in call-out.
** by Tom Limoncelli, tal@warren.mentorg.com
** Copyright (c) 1992, Tom Limoncelli
** The sources can be freely copied for non-commercial use only
** and only if they are unmodified.
**
** Version 2.0 -- See file HISTORY for details.
** $Id: ixocico.c,v 1.4 1992/09/22 17:31:01 root Exp $
$Log: ixocico.c,v $
* Revision 1.4 1992/09/22 17:31:01 root
* set serial parameters to 300bps, 7e1
*
* Revision 1.3 1992/09/21 19:41:31 root
* made a small change to a comment
*
* Revision 1.2 1992/09/21 19:40:22 root
* changed parity to ODD
*
* Revision 1.1 1992/09/21 19:38:02 root
* Initial revision
*
*/
/****************************************************************/
/* USER CONFIGURABLE OPTIONS: */
/* this should be "#define" if you use SunOS, or "#undef" if you
** use HPUX. This controls the name of LOCKDIR and if getpriority()
** is used. I'm sure more needs to be done, but that's a small start.
*/
#define REAL_OS
#ifdef REAL_OS
#define LOCKDIR "/var/spool/uucp"
#else
#define LOCKDIR "/usr/spool/locks"
/* That may not be correct */
#endif
/* not talking to the modem correctly? Try mucking with
the grabmodem() routine. */
/* END OF USER CONFIGURABLE OPTIONS */
/****************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
/* #include <strings.h> */
#include <ctype.h>
#include <errno.h>
#include <sys/termios.h>
#ifdef REAL_OS
#include <sys/time.h> /* required for <sys/resource.h> */
#include <sys/resource.h> /* required for getpriority() */
#endif
/* ASCII constants */
#define STX (2)
#define EOT (4)
#define ACK (6)
#define LF (10)
#define CR (13)
#define NAK (21)
#define ESC (27)
#define RS (30)
#define MAX_PACKET (10000) /* we'll never get a packet this big */
#define MAXLINE (1000)
/* only two little global variables, how's that? */
int modem = 0;
char *lockname = NULL;
/* print a string without worrying about unprintable charactors */
void
safeprint(str)
char *str;
{
while (*str) {
if (isgraph(*str))
(void) fprintf(stdout, "%c", *str);
else {
switch (*str) {
case LF:
(void) fprintf(stdout, "\\n");
break;
case CR:
(void) fprintf(stdout, "\\r");
break;
case 32:
(void) fprintf(stdout, "\\s");
break;
default:
(void) fprintf(stdout, "\\%d", *str);
break;
}
}
str++;
}
fflush(stdout);
}
/* calculate checksum of a packet */
char *checksum(pk)
char *pk;
{
static char check[10];
int sum = 0;
for (;*pk; pk++) sum += *pk;
check[2] = '0' + (sum & 15); sum = sum >> 4;
check[1] = '0' + (sum & 15); sum = sum >> 4;
check[0] = '0' + (sum & 15);
check[3] = 0;
printf("CHECKSUM=:"); safeprint(check); printf(":\n");
return check;
}
/* open the modem. You should have done a lockmodem() first */
int grabmodem(dev)
char *dev;
{
struct termios ti;
int modem;
errno = 0;
modem = open(dev, O_RDWR, 0);
if (errno) {
printf("#MODOPEN modem can't be opened\n");
return 0;
}
/* set tty params to 300bps, even parity, 7-1-e */
errno = 0;
ioctl(modem, TCGETS, &ti);
if (errno) {
close(modem);
return 0;
}
ti.c_iflag |= IGNBRK; /* ignore breaks */
/* ti.c_iflag |= IGNPAR; *//* ignore parity */
ti.c_iflag &= ~INPCK; /* ignore parity errors */
ti.c_iflag |= ISTRIP; /* strip 8th bit */
ti.c_iflag &= ~INLCR; /* don't cr->nl */
ti.c_iflag &= ~ICRNL; /* don't cr->nl */
ti.c_iflag &= ~IGNCR; /* don't ignore cr */
/* ti.c_iflag &= ~IXON; *//* don't do xon */
/* ti.c_iflag &= ~IXOFF; *//* don't do xoff */
ti.c_oflag &= ~OPOST; /* don't post-process */
ti.c_cflag &= ~CBAUD;
ti.c_cflag |= B300; /* baud=300 */
/* ti.c_cflag |= B1200; /* baud=1200 */
ti.c_cflag &= ~CSIZE; /* 7-bit bytes */
ti.c_cflag |= CS7;
/* ti.c_cflag |= CS8; */
ti.c_cflag &= ~CSTOPB; /* one stop bit */
/* ti.c_cflag |= CSTOPB; /* two stop bit */
ti.c_cflag |= PARENB; /* parity */
ti.c_cflag &= ~PARODD; /* even parity */
/* ti.c_cflag |= PARODD; /* odd parity */
ti.c_cflag |= HUPCL; /* hang up on last close */
/* ti.c_cflag |= CRTSCTS; *//* hardware handshaking */
ti.c_cc[VMIN] = 0; /* read() can get as few as 0 bytes */
ti.c_cc[VTIME] = 50; /* time out at 5 seconds no matter what */
ti.c_lflag &= ~ISIG; /* disable signals */
ti.c_lflag &= ~ICANON; /* disable signals */
ti.c_lflag &= ~ECHO; /* don't echo */
errno = 0;
ioctl(modem, TCSETS, &ti);
if (errno) {
close(modem);
return 0;
}
return modem;
}
/* send data to the modem */
void send(fd, str)
int fd;
char *str;
{
printf("Sending: :"); safeprint(str); printf(":\n", str);
write(fd, str, strlen(str));
}
/* wait for a particular string from the modem (err = # of retries permitted ) */
int match(mod, str, err)
int mod;
char *str;
int err;
{
int len;
char c;
printf("MATCHING on :"); safeprint(str); printf(":\n", str);
while (1) {
c = 0;
/* printf("waiting for :%c:\n", *str); */
len = read(mod, &c, 1);
if (len) {
/* printf("got=%d:%c\n", c,c); */
if (c == *str) {
str++;
}
if (!(*str)) break; /* matched all? Exit loop */
}
if (!err--) {
printf("NOT MATCHED\n");
return 1;
}
}
printf("MATCHED\n");
return 0;
}
/* hang up the modem */
void
hangup_modem(fd)
int fd;
{
sleep(3);
send(fd, "+++");
sleep(3);
send(fd, "ATH\r");
sleep(1);
}
/* unlock the modem */
void unlockmodem(name)
char *name;
{
printf("Unlocking modem.\n");
(void)unlink(name);
return;
}
/* clean up and leave this program */
void bail_out()
{
if (modem) {
hangup_modem(modem);
close(modem);
}
if (lockname) unlockmodem(lockname);
exit(0);
}
/* lock the modem OR DIE*/
char *lockmodem(dev)
char *dev;
{
int lock, pid;
int failcnt = 3;
char waitcnt = 0;
char *lkn, lname[200];
strcpy(lname, LOCKDIR);
strcat(lname, "/LCK..");
strcat(lname, 1 + rindex(dev, '/'));
printf("Lockfile = %s\n", lname);
lkn = strdup(lname);
while (failcnt--) {
errno = 0;
lock = open(lname, O_CREAT | O_WRONLY | O_EXCL, 0777);
if (lock == -1) {
#ifdef REAL_OS
printf("Modem is locked, attempting to steal.\n");
/* locked, let's read the cookie in the lock */
pid = 0;
if ((lock = open(lname, O_RDONLY)) != -1) {
(void)read(lock, &pid, sizeof(int) );
printf("Device is locked by process %d\n", pid);
close(lock);
}
printf("Lock = %d\n", lock);
if (pid < 3) {
printf("#MODOPEN device is locked by pid < 3\n");
bail_out();
}
/* see if the process still is alive */
errno = 0;
(void) getpriority(PRIO_PROCESS, pid);
if (errno == ESRCH) { /* lock process dead, let's go! */
if (unlink(lname)) {
printf("#MODOPEN Can't steal lock.\n");
bail_out();
} else {
printf("Lock is stale, stealing!\n");
}
} else {
printf("#MODOPEN Valid lock in the way.\n");
bail_out();
}
#else
printf("#MODOPEN it's locked, I'm out of here!\n");
bail_out();
#endif
} else {
/* lock opened, stuff and go */
pid = getpid();
write(lock, &pid, sizeof(int));
close(lock);
break;
}
}
if (failcnt==-1) {
printf("#MODOPEN Couldn't lock modem after many tries.\n");
bail_out();
}
return lkn;
}
/* get a line from stdin OR DIE */
char *getline(line)
char *line;
{
int len;
char *r;
/* get a line, if EOF return 0 */
if (!(r = fgets(line, MAXLINE, stdin))) return 0;
printf("Data in queue=:"); safeprint(line); printf(":\n", line);
if (!(len = strlen(line))) {
printf("#BADQUEUE Blank line in queued data\n");
bail_out();
}
if (line[len-1] == '\n') {
line[len-1] = 0;
} else {
/* if fgets didn't return a string ending in \n */
printf("#BADQUEUE Data in queue has line too long\n");
bail_out();
}
return r;
}
/* Loop until you get a valid packet. If you get a "message sequence" then
display it. If you get an invalid pack DIE */
void getpacket(fd, str)
int fd;
char *str;
{
int max;
char c;
int len;
char *buf = str;
int err;
*str = 0;
err=50; /* permit up to 500 message sequences or bad packets */
while (err--) {
printf("Getting packet\n");
max = MAX_PACKET;
while (read(fd, &c, 1) == 1) {
if (c == LF) continue; /* skip LF's */
if (c == CR) {
/* don't actually put CR in the string */
break;
}
*buf++ = c;
max--;
if (!max) {
/* packet was too long */
printf("#PACKLEN packet was too long\n");
bail_out();
}
}
*buf = 0;
len = buf - str;
if (len) {
printf("Got packet--length=%d\n", len);
if (isgraph(*str)) {
printf("#GOTMESSEQ message sequece=:");
safeprint(str);
printf(":\n");
return; /* ddj 4/30 */
} else {
/* print packet contents */
printf("packet is data=:"); safeprint(str);
printf(":013:\n");
return;
}
}
}
printf("#LONELY It's too quiet in here. Disconnecting.\n");
bail_out();
}
int main(argc, argv)
int argc;
char *argv[];
{
char dialstring[MAX_PACKET];
char *pack = dialstring; /* use same workspace */
char line[MAXLINE+1];
char pin[MAXLINE+1];
char mesg[MAXLINE+1];
int mesnum, failcnt, len;
char c;
/* check arguments */
if (argc != 3) {
printf("#WRONGARGS wrong number of arguments\n");
bail_out();
}
/* lock modem or die */
lockname = lockmodem( argv[1] );
/* open modem or die */
printf("opening modem\n");
modem = grabmodem( argv[1] );
if (!modem) bail_out();
/* see if modem is awake or hangup; after 3 tries die */
failcnt = 3;
while (failcnt--) {
send(modem, "AT\r");
if (match(modem, "OK", 6)) {
printf("No response. Hang up and try again.\n");
hangup_modem(modem);
while (read(modem, &c, 1)) { /*DONOTHING*/ };
} else break;
}
if (failcnt==-1) bail_out();
printf("dialing\n");
/* send the "A" of "ATDT" */
do {
send(modem, "A");
} while (match(modem, "A", 2));
/* send the rest of the dial string */
sprintf( dialstring, "TDT%s\r", argv[2] );
send(modem, dialstring);
(void) match(modem, argv[2], 10);
/* wait for the modem to connect */
printf("waiting for CONNECT\n");
if (match(modem, "CONNECT", 30)) {
printf("#NOCONN no connect\n");
bail_out();
}
printf("Waiting for ID=\n");
/* send a CR ever second until "ID=" comes back */
failcnt = 10;
/* CRs needed by PacTel DJ */
send(modem, "\r");
/* end of DJ */
while (failcnt--) {
if (match(modem, "ID=", 4)) send(modem, "\r");
else break;
}
if (failcnt==-1) bail_out();
printf("Logging in\n");
failcnt = 3;
while (failcnt--) {
/* switch to "automatic protocol" */
printf("Sending ESC\n");
write(modem, "\033", 1);
send(modem, "PG1000000\r");
printf("Waiting for acceptance (aren't we all)\n");
getpacket(modem, pack);
len = strlen(pack);
if ((len==1) && (*pack == ACK)) {
printf("login successful\n");
break;
}
if ((len==1) && (*pack == NAK)) {
printf("retrying to log in.\n");
continue;
}
if ((len==2) && (*pack == ESC) && (pack[1] == EOT)) {
printf("forced disconnect\n");
bail_out();
}
printf("#UNKNOWNPROTO not the response we're looking for.
Disconnecting.\n");
bail_out();
}
if (failcnt==-1) bail_out();
printf("waiting for message go ahead\n");
failcnt=40;
while (failcnt--) {
getpacket(modem, pack);
if (!strcmp(pack, "\033[p")) break;
}
if (failcnt==-1) bail_out();
printf("got message go-ahead\n");
for (mesnum=0; getline(pin); ) {
getline(mesg);
failcnt=100;
while (failcnt--) {
/* build the packet to be sent */
pack[0] = STX;
pack[1] = 0;
strcat(pack, pin);
strcat(pack, "\r");
strcat(pack, mesg);
strcat(pack, "\r\3"); /* CR then ETX */
strcat(pack, checksum(pack));
strcat(pack, "\r");
send(modem, pack);
/* wait for response and deal */
printf("waiting for validation\n");
getpacket(modem, pack);
len = strlen(pack);
if ((len==1)&&(*pack==ACK)) {
printf("#MESOK %d message xmitted fine\n",
mesnum++);
break;
} else if ((len==1)&&(*pack==NAK)) {
printf("re-retrying message %d\n", mesnum);
} else if ((len==1)&&(*pack==RS)) {
printf("#MESREJECT %d message rejected\n",
mesnum++);
break;
} else if ((len==2)&&(*pack==ESC)&&(*pack==EOT)) {
printf("#FORDIS forced disconnect\n");
bail_out();
}
}
if (failcnt==-1) {
printf("#PROTERR couldn't send packets\n");
bail_out();
}
}
printf("#DONE we're done. Logging out.\n");
send(modem, "\4\r"); /* EOT then CR */
failcnt=3;
while (failcnt--) {
printf("waiting for system logout\n");
getpacket(modem, pack);
len=strlen(pack);
if ((len==2) && (pack[0] == ESC) && (pack[1] == EOT)) {
printf("#BYE asked to hangup\n");
bail_out();
}
if ((len==1)&&(*pack==RS)) {
printf("#WRONGANY something went wrong. (useless msg)\n");
bail_out();
}
/* if (!stricmp(line, "NO CARRIER")) break; */
}
printf("#BYE we're leaving.\n");
bail_out();
}