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