home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_07_05 / v7n5043a.txt < prev    next >
Text File  |  1989-03-08  |  8KB  |  390 lines

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <termio.h>
  4. #include <signal.h>
  5. #include "sc.h"
  6.  
  7. #define BUFFERSIZE 1024
  8.  
  9. static int devicefd; /* file descriptor for special file */
  10. static char devicefn[80];       /* special file name */
  11. static char buffer[BUFFERSIZE];
  12. static struct termio tbufsave;
  13. static BOOLEAN ioctl_done = FALSE;
  14. static BOOLEAN alarmflag;   /* set when alarm goes off */
  15.  
  16. /* -1 cast to ptr to int fcn */
  17. #define BADSIG (void (*)())-1
  18.  
  19. /*
  20.     From Marc J. Rochkinds book, Advanced Unix Programming,
  21.     published by Prentice Hall, Inc.  Used with permission.
  22. */
  23. static void syserr(msg)
  24. char *msg;                        /* message to be printed */
  25. {
  26.     extern int errno, sys_nerr;
  27.     extern char *sys_errlist[];
  28.  
  29.     fprintf(stderr, "ERROR: %s (%d", msg, errno);
  30.     if (errno > 0 && errno < sys_nerr)
  31.         fprintf(stderr, "; %s)\n", sys_errlist[errno]);
  32.     else
  33.         fprintf(stderr, ")\n");
  34.     exit(1);
  35. }
  36.  
  37. /*
  38.     From Marc J. Rochkinds book, Advanced Unix Programming,
  39.     published by Prentice Hall, Inc.  Used with permission.
  40. */
  41. static void fatal(f, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  42. char *f, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10;
  43. {
  44.     char s[120];
  45.     strcpy(s, "FATAL: ");
  46.     strcat(s, f);
  47.     strcat(s, "\n");
  48.     fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  49.     exit(1);
  50. }
  51.  
  52. static void sc_log(f, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
  53. char *f, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10;
  54. {
  55.     static FILE *out = NULL;
  56.     if (out == NULL) {
  57.         unlink("sc_log_file");
  58.         out = fopen("sc_log_file", "w");
  59.         setbuf(out, NULL);
  60.     }
  61.     fprintf(out, f, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
  62. }
  63.  
  64. /*
  65.     attempt to create lock file, return TRUE if successful, 
  66.     FALSE if not
  67. */
  68. static BOOLEAN sc_lock()
  69. {
  70.     char fn[30];
  71.     int x;
  72.     FILE *f;
  73.     for (x = strlen(devicefn); devicefn[x] != '/'; --x)
  74.         ;
  75.     sprintf(fn, "/usr/spool/uucp/LCK..%s", &devicefn[x + 1]);
  76.     sc_log("Lock filename = %s\n", fn);
  77.     if ((f = fopen(fn, "r")) != NULL ) {
  78.         sc_log("Lock file already exists\n");
  79.         return(FALSE);
  80.     }
  81.     if ((f = fopen(fn, "w")) == NULL ) {
  82.         sc_log("Error: Cannot create lock file\n");
  83.         return(FALSE);
  84.     }
  85.     if (fclose(f))
  86.         syserr("fclose");
  87.     sc_log("Lock file created\n");
  88.     return(TRUE);
  89. }
  90.  
  91. /*
  92.     function to remove lock file if received SIGINT or SIGQUIT
  93. */
  94. static void sc_int()
  95. {
  96.     /*
  97.     do whatever else must be done to clean up after your
  98.     application
  99.     */
  100.     sc_cleanup();
  101.     exit(1);
  102. }
  103.  
  104. /*
  105.     returns TRUE if device was opened, FALSE if device could not 
  106.     be opened.
  107.     The method for putting the device in raw mode came from
  108.     Marc J. Rochkinds book, Advanced Unix Programming,
  109.     published by Prentice Hall, Inc.  Used with permission.
  110. */
  111. BOOLEAN sc_open(device, baud_rate, data_bits, stop_bits, parity)
  112. char *device;
  113. int baud_rate;
  114. int data_bits;
  115. int stop_bits;
  116. char parity;
  117. {
  118.     char *errstr;
  119.     struct termio tbuf;
  120.     if (signal(SIGINT, sc_int) == BADSIG)
  121.         syserr("signal");
  122.     if (signal(SIGQUIT, sc_int) == BADSIG)
  123.         syserr("signal");
  124.     if (signal(SIGTERM, sc_int) == BADSIG)
  125.         syserr("signal");
  126.     strcpy(devicefn, device);
  127.     if (! sc_lock()) {
  128.         sc_log("Error: sc_lock returned FALSE\n");
  129.         return(FALSE);
  130.     }
  131.     if ((devicefd = open(device, O_RDWR)) < 0) {
  132.         sc_log("Error: Cannot open device %s\n", device);
  133.         sc_cleanup();
  134.         return(FALSE);
  135.     }
  136.     if (ioctl(devicefd, TCGETA, &tbuf) == -1)
  137.         syserr("ioctl (first call to ioctl)");
  138.     ioctl_done = TRUE;
  139.     tbufsave = tbuf;
  140.     tbuf.c_iflag &= 
  141.       ~ (PARMRK | INPCK | INLCR | ICRNL | IUCLC | BRKINT);
  142.     tbuf.c_iflag |= (ISTRIP | IXON | IXANY | IXOFF);
  143.     tbuf.c_oflag &= ~OPOST;
  144.     tbuf.c_lflag &= ~(ICANON | ISIG | ECHO);
  145.     tbuf.c_cflag = 0;
  146.     tbuf.c_cc[4] = 1;
  147.     tbuf.c_cc[5] = 1;
  148.     switch(baud_rate) {
  149.     case 300:
  150.         tbuf.c_cflag |= B300;
  151.         break;
  152.     case 1200:
  153.         tbuf.c_cflag |= B1200;
  154.         break;
  155.     case 2400:
  156.         tbuf.c_cflag |= B2400;
  157.         break;
  158.     case 4800:
  159.         tbuf.c_cflag |= B4800;
  160.         break;
  161.     case 9600:
  162.         tbuf.c_cflag |= B9600;
  163.         break;
  164.     default:
  165.         errstr = "Error: Invalid baud rate\n";
  166.         sc_log(errstr);
  167.         sc_cleanup();
  168.         fatal(errstr);
  169.     }
  170.     switch(data_bits) {
  171.     case 7:
  172.         tbuf.c_cflag |= CS7;
  173.         break;
  174.     case 8:
  175.         tbuf.c_cflag |= CS8;
  176.         break;
  177.     default:
  178.         errstr = "Error: Invalid number of data bits\n";
  179.         sc_log(errstr);
  180.         sc_cleanup();
  181.         fatal(errstr);
  182.     }
  183.     switch(stop_bits) {
  184.     case 1:
  185.         break;
  186.     case 2:
  187.         tbuf.c_cflag |= CSTOPB;
  188.         break;
  189.     default:
  190.         errstr = "Error: Invalid number of stop bits\n";
  191.         sc_log(errstr);
  192.         sc_cleanup();
  193.         fatal(errstr);
  194.     }
  195.     switch(parity) {
  196.     case 'E':
  197.         tbuf.c_cflag |= PARENB;
  198.         break;
  199.     case 'O':
  200.         tbuf.c_cflag |= PARENB;
  201.         tbuf.c_cflag |= PARODD;
  202.         break;
  203.     case 'N':
  204.         break;
  205.     default:
  206.         errstr = "Error: Invalid parity\n";
  207.         sc_log(errstr);
  208.         sc_cleanup();
  209.         fatal(errstr);
  210.     }
  211.     tbuf.c_cflag |= CREAD;
  212.     tbuf.c_cflag |= HUPCL;
  213.     tbuf.c_cflag |= CLOCAL;
  214.     if (ioctl(devicefd, TCSETAF, &tbuf) == -1)
  215.         syserr("ioctl (second call to ioctl)");
  216.     return(TRUE);
  217. }
  218.  
  219. /*
  220. close the device
  221. */
  222. void sc_close()
  223. {
  224.     sc_log("Closing the device\n");
  225.     sc_cleanup();
  226.     if (close(devicefd) < 0)
  227.         syserr("close");
  228. }
  229.  
  230. /*
  231. returns TRUE if CONNECTed to the remote system
  232. */
  233. BOOLEAN sc_dial(phone_number)
  234. char *phone_number;
  235. {
  236.     char *errstr;
  237.     char s[200];
  238.     int x;
  239.     BOOLEAN b;
  240.     sc_log("Attempting to get attention of modem\n");
  241.     sc_write("ATH\r");
  242.     if (! sc_read(buffer, sizeof(buffer), 4, "OK")) {
  243.         sc_log("Attempting to get attention of modem\n");
  244.         sc_write("ATH\r");
  245.         if (! sc_read(buffer, sizeof(buffer), 4, "OK")) {
  246.             sc_log("Attempting to get attention of modem\n");
  247.             sc_write("+++");
  248.             if (! sc_read(buffer, sizeof(buffer), 4, "OK")) {
  249.                 sc_log("Attempting to get attention of modem\n");
  250.                 sc_write("ATH\r");
  251.                 if (! sc_read(buffer, sizeof(buffer), 4, "OK")) {
  252.                     errstr = 
  253.                       "Error: could not get attention of modem\n";
  254.                     sc_log(errstr);
  255.                     return(FALSE);
  256.                 }
  257.             }
  258.         }
  259.     }
  260.     sc_log("Got attention of modem\n");
  261.     sc_log("Dialing phone number (%s)\n", phone_number);
  262.     sprintf(s, "ATDT%s\r", phone_number);
  263.     sc_write(s);
  264.     b = sc_read(buffer, sizeof(buffer), 30, "CONNECT");
  265.     if (!b) {
  266.         errstr = "Error: Did not get CONNECT\n";
  267.         sc_log(errstr);
  268.         sc_hangup();
  269.         return(FALSE);
  270.     }
  271.     sc_log("Got CONNECT\n");
  272.     return(TRUE);
  273. }
  274.  
  275. /*
  276. hangup the modem
  277. */
  278. void sc_hangup()
  279. {
  280.     char ch;
  281.     int x, stat;
  282.     BOOLEAN b;
  283.     sc_log("Hanging up\n");
  284.     buffer[0] = '\0';
  285.     sc_log("Attempting to get attention of modem\n");
  286.     sc_write("+++");
  287.     if (sc_read(buffer, sizeof(buffer), 4, "OK"))
  288.         sc_log("Got attention of modem\n");
  289.     else {
  290.         sc_write("+++");
  291.         if (sc_read(buffer, sizeof(buffer), 4, "OK"))
  292.             sc_log("Got attention of modem\n");
  293.     }
  294.     sc_write("ATH\r");
  295.     if (sc_read(buffer, sizeof(buffer), 4, "OK"))
  296.         sc_log("Successful hangup\n");
  297.     sc_write("ATH\r");
  298.     if (sc_read(buffer, sizeof(buffer), 4, "OK"))
  299.         sc_log("Successful hangup\n");
  300. }
  301.  
  302. static void sc_alarm()
  303. {
  304.     alarmflag = TRUE;
  305. }
  306.  
  307. /*
  308. returns TRUE if pattern was found, FALSE if time ran out
  309. */
  310. BOOLEAN sc_read(buffer, len, seconds, pattern)
  311. char *buffer;
  312. int len;
  313. int seconds;    /* number of seconds to wait if we don't get 
  314.                    the correct pattern */
  315. char *pattern;
  316. {
  317.     char *errstr;
  318.     int c, sl, x, status;
  319.     sl = strlen(pattern);
  320.     alarmflag = FALSE;
  321.     c = x = 0;
  322.     if (signal(SIGALRM, sc_alarm) == BADSIG)
  323.         syserr("signal");
  324.     alarm(seconds);
  325.     while(TRUE) {
  326.         if (x == len - 1) {
  327.             errstr = "Error: Buffer overflow\n";
  328.             sc_log(errstr);
  329.             sc_cleanup();
  330.             fatal(errstr);
  331.         }
  332.         status = read(devicefd, &buffer[x], 1);
  333.         if (status <= 0 || alarmflag == TRUE) {
  334.             alarm(0);
  335.             sc_log(
  336.               "Error: Pattern not matched in allotted time\n");
  337.             return(FALSE);
  338.         }
  339.         buffer[x] &= 0177;
  340.         buffer[x + 1] = '\0';
  341.         if (pattern[c] == buffer[x])
  342.             ++c;
  343.         else
  344.             c = 0;
  345.         if (c == sl) {
  346.             alarm(0);
  347.             return(TRUE);
  348.         }
  349.         ++x;
  350.     }
  351. }
  352.  
  353. /*
  354. Write a string to the device
  355. */
  356. void sc_write(s)
  357. char *s;
  358. {
  359.     int x;
  360.     x = strlen(s);
  361.     if (write(devicefd, s, (unsigned)x) <= 0)
  362.         syserr("write");
  363.     /*
  364.     Another method for writing this function when it is
  365.     neccessary to slow down the rate at which characters 
  366.     are sent:
  367.     */
  368.     /*
  369.     for(x = 0; s[x] != '\0'; ++x) { 
  370.         if (write(devicefd, &s[x], 1) <= 0)
  371.             syserr("write");
  372.         nap(20L);
  373.     }
  374.     */
  375. }
  376.  
  377. void sc_cleanup()
  378. {
  379.     int x;
  380.     char fn[60];
  381.     if (ioctl_done)
  382.         if (ioctl(devicefd, TCSETAF, &tbufsave) == -1)
  383.             syserr("ioctl3");
  384.     for (x = strlen(devicefn); devicefn[x] != '/'; --x);
  385.     sprintf(fn, "/usr/spool/uucp/LCK..%s", &devicefn[x + 1]);
  386.     if (unlink(fn))
  387.         syserr("unlink");
  388. }
  389.  
  390.