home *** CD-ROM | disk | FTP | other *** search
/ Telecom / 1996-04-telecom-walnutcreek.iso / technical / ixo.program.scripts / ixocico.c < prev    next >
C/C++ Source or Header  |  1993-02-14  |  13KB  |  581 lines

  1. /* ixocico -- IXO protocol call-in call-out.
  2. **   by Tom Limoncelli, tal@warren.mentorg.com
  3. **   Copyright (c) 1992, Tom Limoncelli
  4. **   The sources can be freely copied for non-commercial use only
  5. **   and only if they are unmodified.
  6. **
  7. ** Version 2.0 -- See file HISTORY for details.
  8. **  $Id: ixocico.c,v 1.4 1992/09/22 17:31:01 root Exp $
  9.  
  10. $Log: ixocico.c,v $
  11.  * Revision 1.4  1992/09/22  17:31:01  root
  12.  * set serial parameters to 300bps, 7e1
  13.  *
  14.  * Revision 1.3  1992/09/21  19:41:31  root
  15.  * made a small change to a comment
  16.  *
  17.  * Revision 1.2  1992/09/21  19:40:22  root
  18.  * changed parity to ODD
  19.  *
  20.  * Revision 1.1  1992/09/21  19:38:02  root
  21.  * Initial revision
  22.  *
  23.  
  24. */
  25.  
  26. /****************************************************************/
  27. /* USER CONFIGURABLE OPTIONS: */
  28.  
  29. /* this should be "#define" if you use SunOS, or "#undef" if you
  30. ** use HPUX.  This controls the name of LOCKDIR and if getpriority()
  31. ** is used.  I'm sure more needs to be done, but that's a small start.
  32. */
  33. #define REAL_OS
  34.  
  35. #ifdef REAL_OS
  36. #define LOCKDIR    "/var/spool/uucp"
  37. #else
  38. #define LOCKDIR "/usr/spool/locks"
  39. /* That may not be correct */
  40. #endif
  41.  
  42. /* not talking to the modem correctly?  Try mucking with
  43. the grabmodem() routine.  */
  44.  
  45. /* END OF USER CONFIGURABLE OPTIONS */
  46. /****************************************************************/
  47.  
  48. #include <stdio.h>
  49. #include <fcntl.h>
  50. #include <string.h>
  51. /* #include <strings.h> */
  52. #include <ctype.h>
  53. #include <errno.h>
  54. #include <sys/termios.h>
  55.  
  56. #ifdef REAL_OS
  57. #include <sys/time.h>        /* required for <sys/resource.h> */
  58. #include <sys/resource.h>    /* required for getpriority() */
  59. #endif
  60.  
  61. /* ASCII constants */
  62. #define STX (2)
  63. #define EOT (4)
  64. #define ACK (6)
  65. #define LF (10)
  66. #define CR (13)
  67. #define NAK (21)
  68. #define ESC (27)
  69. #define RS (30)
  70.  
  71. #define MAX_PACKET    (10000)    /* we'll never get a packet this big */
  72. #define MAXLINE    (1000)
  73.  
  74. /* only two little global variables, how's that? */
  75.  
  76. int modem = 0;
  77. char *lockname = NULL;
  78.  
  79. /* print a string without worrying about unprintable charactors */
  80. void 
  81.  
  82. safeprint(str)
  83. char           *str;
  84. {
  85.     while (*str) {
  86.         if (isgraph(*str))
  87.             (void) fprintf(stdout, "%c", *str);
  88.         else {
  89.             switch (*str) {
  90.             case LF:
  91.                 (void) fprintf(stdout, "\\n");
  92.                 break;
  93.             case CR:
  94.                 (void) fprintf(stdout, "\\r");
  95.                 break;
  96.             case 32:
  97.                 (void) fprintf(stdout, "\\s");
  98.                 break;
  99.             default:
  100.                 (void) fprintf(stdout, "\\%d", *str);
  101.                 break;
  102.             }
  103.         }
  104.         str++;
  105.     }
  106.     fflush(stdout);
  107. }
  108.  
  109. /* calculate checksum of a packet */
  110. char *checksum(pk)
  111. char *pk;
  112. {
  113.     static char check[10];
  114.     int sum = 0;
  115.  
  116.     for (;*pk; pk++) sum += *pk;
  117.     check[2] = '0' + (sum & 15); sum = sum >> 4;
  118.     check[1] = '0' + (sum & 15); sum = sum >> 4;
  119.     check[0] = '0' + (sum & 15);
  120.     check[3] = 0;
  121.  
  122. printf("CHECKSUM=:"); safeprint(check); printf(":\n");
  123.     return check;
  124. }
  125.  
  126. /* open the modem.  You should have done a lockmodem() first */
  127. int grabmodem(dev)
  128. char           *dev;
  129. {
  130.     struct termios  ti;
  131.     int             modem;
  132.  
  133.     errno = 0;
  134.     modem = open(dev, O_RDWR, 0);
  135.     if (errno) {
  136.         printf("#MODOPEN modem can't be opened\n");
  137.         return 0;
  138.     }
  139.  
  140.     /* set tty params to 300bps, even parity, 7-1-e */
  141.     errno = 0;
  142.     ioctl(modem, TCGETS, &ti);
  143.     if (errno) {
  144.         close(modem);
  145.         return 0;
  146.     }
  147.     ti.c_iflag |= IGNBRK;   /* ignore breaks */
  148.     /* ti.c_iflag |= IGNPAR; *//* ignore parity */
  149.     ti.c_iflag &= ~INPCK;   /* ignore parity errors */
  150.     ti.c_iflag |= ISTRIP;   /* strip 8th bit */
  151.     ti.c_iflag &= ~INLCR;   /* don't cr->nl */
  152.     ti.c_iflag &= ~ICRNL;   /* don't cr->nl */
  153.     ti.c_iflag &= ~IGNCR;   /* don't ignore cr */
  154.     /* ti.c_iflag &= ~IXON; *//* don't do xon */
  155.     /* ti.c_iflag &= ~IXOFF; *//* don't do xoff */
  156.  
  157.     ti.c_oflag &= ~OPOST;   /* don't post-process */
  158.  
  159.     ti.c_cflag &= ~CBAUD;
  160.     ti.c_cflag |= B300;    /* baud=300 */
  161.     /* ti.c_cflag |= B1200;    /* baud=1200 */
  162.  
  163.     ti.c_cflag &= ~CSIZE;   /* 7-bit bytes */
  164.     ti.c_cflag |= CS7;
  165. /*    ti.c_cflag |= CS8; */
  166.  
  167.     ti.c_cflag &= ~CSTOPB;  /* one stop bit */
  168. /*    ti.c_cflag |= CSTOPB;  /* two stop bit */
  169.  
  170.     ti.c_cflag |= PARENB;      /* parity */
  171.     ti.c_cflag &= ~PARODD;  /* even parity */
  172. /*    ti.c_cflag |= PARODD;  /* odd parity */
  173.  
  174.     ti.c_cflag |= HUPCL;    /* hang up on last close */
  175.     /* ti.c_cflag |= CRTSCTS; *//* hardware handshaking */
  176.     ti.c_cc[VMIN] = 0;  /* read() can get as few as 0 bytes */
  177.     ti.c_cc[VTIME] = 50;    /* time out at 5 seconds no matter what */
  178.  
  179.     ti.c_lflag &= ~ISIG;    /* disable signals */
  180.     ti.c_lflag &= ~ICANON;  /* disable signals */
  181.     ti.c_lflag &= ~ECHO;    /* don't echo */
  182.  
  183.     errno = 0;
  184.     ioctl(modem, TCSETS, &ti);
  185.     if (errno) {
  186.         close(modem);
  187.         return 0;
  188.     }
  189.     return modem;
  190. }
  191.  
  192. /* send data to the modem */
  193. void send(fd, str)
  194. int             fd;
  195. char           *str;
  196. {
  197.     printf("Sending: :"); safeprint(str); printf(":\n", str);
  198.     write(fd, str, strlen(str));
  199. }
  200.  
  201. /* wait for a particular string from the modem (err = # of retries permitted ) */
  202. int match(mod, str, err) 
  203.  
  204.     int mod;
  205.     char *str;
  206.     int err;
  207. {
  208.     int len;
  209.     char c;
  210.  
  211. printf("MATCHING on :"); safeprint(str); printf(":\n", str);
  212.  
  213.     while (1) {
  214.         c = 0;
  215. /* printf("waiting for :%c:\n", *str); */
  216.         len = read(mod, &c, 1);
  217.         if (len) {
  218. /* printf("got=%d:%c\n", c,c); */
  219.             if (c == *str) {
  220.                 str++;
  221.             }
  222.             if (!(*str)) break; /* matched all?  Exit loop */
  223.         }
  224.         if (!err--) {
  225.             printf("NOT MATCHED\n");
  226.             return 1;
  227.         }
  228.     }
  229. printf("MATCHED\n");
  230.     return 0;
  231. }
  232.  
  233. /* hang up the modem */
  234. void 
  235.  
  236. hangup_modem(fd)
  237. int             fd;
  238. {
  239.     sleep(3);
  240.     send(fd, "+++");
  241.     sleep(3);
  242.     send(fd, "ATH\r");
  243.     sleep(1);
  244. }
  245.  
  246. /* unlock the modem */
  247. void unlockmodem(name)
  248. char           *name;
  249. {
  250.     printf("Unlocking modem.\n");
  251.     (void)unlink(name);
  252.     return;
  253. }
  254.  
  255. /* clean up and leave this program */
  256. void bail_out()
  257. {
  258.     if (modem) {
  259.         hangup_modem(modem);
  260.         close(modem);
  261.     }
  262.     if (lockname) unlockmodem(lockname);
  263.     exit(0);
  264. }
  265.  
  266. /* lock the modem OR DIE*/
  267. char *lockmodem(dev)
  268. char           *dev;
  269. {
  270.     int lock, pid;
  271.     int failcnt = 3;
  272.     char waitcnt = 0;
  273.     char *lkn, lname[200];
  274.  
  275.     strcpy(lname, LOCKDIR);
  276.     strcat(lname, "/LCK..");
  277.     strcat(lname, 1 + rindex(dev, '/'));
  278.  
  279. printf("Lockfile = %s\n", lname);
  280.     lkn = strdup(lname);
  281.     while (failcnt--) {
  282.         errno = 0;
  283.         lock = open(lname, O_CREAT | O_WRONLY | O_EXCL, 0777);
  284.         if (lock == -1) {
  285. #ifdef REAL_OS
  286.             printf("Modem is locked, attempting to steal.\n");
  287.             /* locked, let's read the cookie in the lock */
  288.             pid = 0;
  289.             if ((lock = open(lname, O_RDONLY)) != -1) {
  290.                 (void)read(lock, &pid, sizeof(int) );
  291.                 printf("Device is locked by process %d\n", pid);
  292.                 close(lock);
  293.             }
  294.             printf("Lock = %d\n", lock);
  295.             if (pid < 3) {
  296.                 printf("#MODOPEN device is locked by pid < 3\n");
  297.                 bail_out();
  298.             }
  299.             /* see if the process still is alive */
  300.             errno = 0;
  301.             (void) getpriority(PRIO_PROCESS, pid);
  302.             if (errno == ESRCH) {   /* lock process dead, let's go! */
  303.                 if (unlink(lname)) {
  304.                     printf("#MODOPEN Can't steal lock.\n");
  305.                     bail_out();
  306.                 } else {
  307.                     printf("Lock is stale, stealing!\n");
  308.                 }
  309.             } else {
  310.                 printf("#MODOPEN Valid lock in the way.\n");
  311.                 bail_out();
  312.             }
  313. #else
  314.             printf("#MODOPEN it's locked, I'm out of here!\n");
  315.             bail_out();
  316. #endif
  317.         } else {
  318.             /* lock opened, stuff and go */
  319.             pid = getpid();
  320.             write(lock, &pid, sizeof(int));
  321.             close(lock);
  322.             break;
  323.         }
  324.     }
  325.     if (failcnt==-1) {
  326.         printf("#MODOPEN Couldn't lock modem after many tries.\n");
  327.         bail_out();
  328.     }
  329.     return lkn;
  330. }
  331.  
  332. /* get a line from stdin OR DIE */
  333. char *getline(line)
  334. char *line;
  335. {
  336.     int len;
  337.     char *r;
  338.  
  339.     /* get a line, if EOF return 0 */
  340.     if (!(r = fgets(line, MAXLINE, stdin))) return 0;
  341.  
  342.     printf("Data in queue=:"); safeprint(line); printf(":\n", line);
  343.  
  344.     if (!(len = strlen(line))) {
  345.         printf("#BADQUEUE Blank line in queued data\n");
  346.         bail_out();
  347.     }
  348.  
  349.     if (line[len-1] == '\n') {
  350.         line[len-1] = 0;
  351.     } else {
  352.         /* if fgets didn't return a string ending in \n */
  353.         printf("#BADQUEUE Data in queue has line too long\n");
  354.         bail_out();
  355.     }
  356.     return r;
  357. }
  358.  
  359. /* Loop until you get a valid packet.  If you get a "message sequence" then
  360. display it.  If you get an invalid pack DIE */
  361.  
  362. void getpacket(fd, str)
  363. int fd;
  364. char *str;
  365. {
  366.     int max;
  367.     char c;
  368.     int len;
  369.     char *buf = str;
  370.     int err;
  371.  
  372.     *str = 0;
  373.     err=50;    /* permit up to 500 message sequences or bad packets */
  374.     while (err--) {
  375.         printf("Getting packet\n");
  376.         max = MAX_PACKET;
  377.         while (read(fd, &c, 1) == 1) {
  378.             if (c == LF) continue;    /* skip LF's */
  379.             if (c == CR) {
  380.                 /* don't actually put CR in the string */
  381.                 break;
  382.             }
  383.             *buf++ = c;
  384.             max--;
  385.             if (!max) {
  386.                 /* packet was too long */
  387.                 printf("#PACKLEN packet was too long\n");
  388.                 bail_out();
  389.             }
  390.         }
  391.         *buf = 0;
  392.         len =  buf - str;
  393.         if (len) {
  394.             printf("Got packet--length=%d\n", len);
  395.             if (isgraph(*str)) {
  396.                 printf("#GOTMESSEQ message sequece=:");
  397.                 safeprint(str);
  398.                 printf(":\n");
  399.                 return;        /* ddj 4/30  */
  400.             } else {
  401.                 /* print packet contents */
  402.                 printf("packet is data=:"); safeprint(str);  
  403. printf(":013:\n");
  404.                 return;
  405.             }
  406.         }
  407.     }
  408.     printf("#LONELY It's too quiet in here.  Disconnecting.\n");
  409.     bail_out();
  410. }
  411.  
  412. int main(argc, argv)
  413. int argc;
  414. char *argv[];
  415. {
  416.     char dialstring[MAX_PACKET];
  417.     char *pack = dialstring;    /* use same workspace */
  418.     char line[MAXLINE+1];
  419.     char pin[MAXLINE+1];
  420.     char mesg[MAXLINE+1];
  421.     int mesnum, failcnt, len;
  422.     char c;
  423.  
  424.     /* check arguments */
  425.     if (argc != 3) {
  426.         printf("#WRONGARGS wrong number of arguments\n");
  427.         bail_out();
  428.     }
  429.  
  430.     /* lock modem or die */
  431.     lockname = lockmodem( argv[1] );
  432.     /* open modem or die */
  433.     printf("opening modem\n");
  434.     modem = grabmodem( argv[1] );
  435.     if (!modem) bail_out();
  436.  
  437.     /* see if modem is awake or hangup; after 3 tries die */
  438.     failcnt = 3;
  439.     while (failcnt--) {
  440.         send(modem, "AT\r");
  441.         if (match(modem, "OK", 6)) {
  442.             printf("No response.  Hang up and try again.\n");
  443.             hangup_modem(modem);
  444.             while (read(modem, &c, 1)) { /*DONOTHING*/ };
  445.         } else break;
  446.     }
  447.     if (failcnt==-1) bail_out();
  448.  
  449. printf("dialing\n");
  450.  
  451.     /* send the "A" of "ATDT" */
  452.     do {
  453.         send(modem, "A");
  454.     } while (match(modem, "A", 2));
  455.     /* send the rest of the dial string */
  456.     sprintf( dialstring, "TDT%s\r", argv[2] );
  457.     send(modem, dialstring);
  458.     (void) match(modem, argv[2], 10);
  459.  
  460.     /* wait for the modem to connect */
  461.     printf("waiting for CONNECT\n");
  462.     if (match(modem, "CONNECT", 30)) {
  463.         printf("#NOCONN no connect\n");
  464.         bail_out();
  465.     }
  466.  
  467. printf("Waiting for ID=\n");
  468.  
  469.     /* send a CR ever second until "ID=" comes back */
  470.     failcnt = 10;
  471.     /* CRs needed by PacTel   DJ */
  472.     send(modem, "\r");
  473.     /* end of DJ */
  474.     while (failcnt--) {
  475.         if (match(modem, "ID=", 4)) send(modem, "\r");
  476.         else break;
  477.     }
  478.     if (failcnt==-1) bail_out();
  479.  
  480. printf("Logging in\n");
  481.  
  482.     failcnt = 3;
  483.     while (failcnt--) {
  484.         /* switch to "automatic protocol" */
  485.         printf("Sending ESC\n");
  486.         write(modem, "\033", 1);
  487.         send(modem, "PG1000000\r");
  488.  
  489.     printf("Waiting for acceptance (aren't we all)\n");
  490.         getpacket(modem, pack);
  491.         len = strlen(pack);
  492.         if ((len==1) && (*pack == ACK)) {
  493.             printf("login successful\n");
  494.             break;
  495.         }
  496.         if ((len==1) && (*pack == NAK)) {
  497.             printf("retrying to log in.\n");
  498.             continue;
  499.         }
  500.         if ((len==2) && (*pack == ESC) && (pack[1] == EOT)) {
  501.             printf("forced disconnect\n");
  502.             bail_out();
  503.         }
  504.         printf("#UNKNOWNPROTO not the response we're looking for.   
  505. Disconnecting.\n");
  506.         bail_out();
  507.     }
  508.     if (failcnt==-1) bail_out();
  509.  
  510. printf("waiting for message go ahead\n");
  511.     failcnt=40;
  512.     while (failcnt--) {
  513.         getpacket(modem, pack);
  514.         if (!strcmp(pack, "\033[p")) break;
  515.     }
  516.     if (failcnt==-1) bail_out();
  517.     printf("got message go-ahead\n");
  518.  
  519.     for (mesnum=0; getline(pin); ) {
  520.         getline(mesg);
  521.         failcnt=100;
  522.         while (failcnt--) {
  523.             /* build the packet to be sent */
  524.             pack[0] = STX;
  525.             pack[1] = 0;
  526.             strcat(pack, pin);
  527.             strcat(pack, "\r");
  528.             strcat(pack, mesg);
  529.             strcat(pack, "\r\3");    /* CR then ETX */
  530.             strcat(pack, checksum(pack));
  531.             strcat(pack, "\r");
  532.             send(modem, pack);
  533.     
  534.             /* wait for response and deal */
  535.             printf("waiting for validation\n");
  536.             getpacket(modem, pack);
  537.             len = strlen(pack);
  538.             if ((len==1)&&(*pack==ACK)) {
  539.                 printf("#MESOK %d message xmitted fine\n",  
  540. mesnum++);
  541.                 break;
  542.             } else if ((len==1)&&(*pack==NAK)) {
  543.                 printf("re-retrying message %d\n", mesnum);
  544.             } else if ((len==1)&&(*pack==RS)) {
  545.                 printf("#MESREJECT %d message rejected\n",  
  546. mesnum++);
  547.                 break;
  548.             } else if ((len==2)&&(*pack==ESC)&&(*pack==EOT)) {
  549.                 printf("#FORDIS forced disconnect\n");
  550.                 bail_out();
  551.             }
  552.         }
  553.         if (failcnt==-1) {
  554.             printf("#PROTERR couldn't send packets\n");
  555.             bail_out();
  556.         }
  557.     }
  558.     printf("#DONE we're done.  Logging out.\n");
  559.     send(modem, "\4\r");    /* EOT then CR */
  560.  
  561.     failcnt=3;
  562.     while (failcnt--) {
  563.         printf("waiting for system logout\n");
  564.         getpacket(modem, pack);
  565.         len=strlen(pack);
  566.         if ((len==2) && (pack[0] == ESC) && (pack[1] == EOT)) {
  567.             printf("#BYE asked to hangup\n");
  568.             bail_out();
  569.         }
  570.         if ((len==1)&&(*pack==RS)) {
  571.             printf("#WRONGANY something went wrong. (useless msg)\n");
  572.             bail_out();
  573.         }
  574. /*        if (!stricmp(line, "NO CARRIER")) break; */
  575.     }
  576.     printf("#BYE we're leaving.\n");
  577.     bail_out();
  578. }
  579.  
  580.  
  581.