home *** CD-ROM | disk | FTP | other *** search
- /* 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 1.0 -- See file HISTORY for details.
- */
-
- /****************************************************************/
- /* 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 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; /* baud=300 */
- ti.c_cflag |= B300;
- ti.c_cflag &= ~CSIZE; /* 8-bit bytes */
- ti.c_cflag |= CS8;
- ti.c_cflag &= ~CSTOPB; /* one stop bit */
- ti.c_cflag &= ~PARENB; /* parity */
- ti.c_cflag &= ~PARODD; /* even 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 times to re-try) */
- 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");
- } 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", 9)) {
- 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", 400)) {
- printf("#NOCONN no connect\n");
- bail_out();
- }
-
- printf("Waiting for ID=\n");
-
- /* send a CR ever second until "ID=" comes back */
- while (1) {
- if (match(modem, "ID=", 100)) send(modem, "\r");
- else break;
- }
-
- 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();
- }
-
-
-