home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / pcomm / part04 / port.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-17  |  6.0 KB  |  247 lines

  1. /*
  2.  * Routines to get or release a tty port.
  3.  */
  4.  
  5. #define LOCKDIR "/usr/spool/uucp"
  6. #undef ASCII_PID
  7.  
  8. #include <stdio.h>
  9. #include <fcntl.h>
  10. #include <termio.h>
  11. #ifdef UNIXPC
  12. #include <sys/phone.h>
  13. #endif /* UNIXPC */
  14. #include "dial_dir.h"
  15. #include "modem.h"
  16. #include "status.h"
  17.  
  18. int getty_status;
  19. /*
  20.  * Finds a free (or requested) serial port.  Creates a lock file to hold
  21.  * it for our use.  Loads the modem database.  A return code of 1 means
  22.  * all ports (or the requested port) are busy.
  23.  */
  24.  
  25. int
  26. get_port()
  27. {
  28.     int i, j, k, progpid, fd, list[NUM_TTY];
  29.     char file[80], buf[80], message[80], *strdup();
  30.     void error_win(), line_set(), release_port(), send_str();
  31.     void free_ptr();
  32.     
  33.     /*
  34.      * If we already have a port, see if it is good enough for the
  35.      * current request.
  36.      */
  37.     if (status->fd != -1) {
  38.         if (!strcmp(dir->index[dir->d_cur], modem->tty[modem->t_cur]) ||
  39.          modem->mbaud[modem->t_cur] >= dir->baud[dir->d_cur]) {
  40.             /*
  41.              * Re-initialize the modem because the baud
  42.              * rate (or other parameters) may have changed.
  43.              */
  44.             line_set();
  45.             send_str(modem->init[modem->m_cur]);
  46.             return(0);
  47.         }
  48.     }
  49.     release_port(1);
  50.  
  51.     /*
  52.      * See if you want a specific tty port.  If the index field in the
  53.      * dialing directory is a valid device name, then use that tty.
  54.      */
  55.     sprintf(buf, "/dev/%s", dir->index[dir->d_cur]);
  56.     list[0] = -1;
  57.                     /* if index is a valid device */
  58.     if (!access(buf, 0)) {
  59.         for (i=0; i<modem->t_entries; i++) {
  60.                     /* and it exists in modem database */
  61.             if (!strcmp(dir->index[dir->d_cur], modem->tty[i])) {
  62.                 list[0] = i;
  63.                 list[1] = -1;
  64.                 break;
  65.             }
  66.         }
  67.     }
  68.  
  69.     /*
  70.      * Create a list of acceptable ttys.  It searches the tty database
  71.      * for the requested baud rate.
  72.      */
  73.     k = 0;
  74.     if (list[0] == -1) {
  75.         for (i=0; i<modem->t_entries; i++) {
  76.                     /* skip ports with no modems */
  77.             if (!strcmp(modem->tname[i], "DIRECT"))
  78.                 continue;
  79.  
  80.                     /* can handle requested baud rate ? */
  81.             if (modem->mbaud[i] >= dir->baud[dir->d_cur])
  82.                 list[k++] = i;
  83.         }
  84.                     /* the end of list marker */
  85.         list[k] = -1;
  86.     }
  87.                     /* empty list ? */
  88.     if (list[0] == -1) {
  89.         sprintf(message, "No modem at a %d baud rating exists in", dir->baud[dir->d_cur]);
  90.         sprintf(file, "modem file '%s'", status->m_path);
  91.         error_win(0, message, file);
  92.         return(1);
  93.     }
  94.                     /* check the list for a free port */    
  95.     i = 0;
  96.     while (list[i] != -1) {
  97.                     /* create a lock file name */
  98.         sprintf(file, "%s/LCK..%s", LOCKDIR, modem->tty[list[i]]);
  99.  
  100.         /*
  101.          * See if the lock file exists... We DO NOT look to see
  102.          * if the pid in the file is still active.  Maybe I'll
  103.          * change this later...
  104.          */
  105.         if (access(file, 0)) {
  106.             getty_status = set_getty(modem->tty[list[i]], 0);
  107.             
  108.             if ((fd = open(file, O_CREAT|O_WRONLY, 0666)) < 0) {
  109.                 set_getty(modem->tty[list[i]], 1);
  110.                 sprintf(buf, "'%s'", file);
  111.                 error_win(1, "Can't create the lockfile", buf);
  112.             }
  113. #ifdef ASCII_PID
  114.             sprintf(buf, "%10d\n", getpid());
  115.             write(fd, buf, 11);
  116. #else /* ASCII_PID */
  117.             progpid = getpid();
  118.             write(fd, (char *)&progpid, sizeof(int));
  119. #endif /* ASCII_PID */
  120.             close(fd);
  121.                     /* store the new values */
  122.             free_ptr(status->lock_path);
  123.             status->lock_path = strdup(file);
  124.             modem->t_cur = list[i];
  125.  
  126.                     /* open the device (hold DTR high) */
  127.             sprintf(buf, "/dev/%s", modem->tty[list[i]]);
  128.             if ((fd = open(buf, O_RDWR|O_NDELAY)) < 0) {
  129.                 set_getty(modem->tty[list[i]], 1);
  130.                 sprintf(file, "Can't open port '%s' for read and write", buf);
  131.                 error_win(1, file, NULL);
  132.             }
  133.  
  134.                     /* turn off the "no delay" mode */
  135.             fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY);
  136.             status->fd = fd;
  137.                     /* change line settings */
  138.             line_set();
  139.                     /* load the modem data base */
  140.             for (j=0; j<modem->m_entries; j++) {
  141.                 if (!strcmp(modem->tname[list[i]], modem->mname[j])) {
  142.                     modem->m_cur = j;
  143.                     break;
  144.                 }
  145.             }
  146.                     /* initialize the modem */
  147.             send_str(modem->init[j]);
  148.             return(0);
  149.         }
  150.         i++;
  151.     }
  152.     error_win(0, "All ports are busy now, try again later", NULL);
  153.     return(1);
  154. }
  155.  
  156. /*
  157.  * Release the port.  Closes the file descriptor and removes the
  158.  * lock file
  159.  */
  160.  
  161. void
  162. release_port(verbose)
  163. int verbose;
  164. {
  165.     char buf[80];
  166.     extern char *null_ptr;
  167.     void free_ptr(), hang_up();
  168.  
  169.     /*
  170.      * The modem structure can't be guaranteed to exist yet.  For example,
  171.      * an error in reading one of the other support files would cause
  172.      * this routine to be used before the MODEM structure gets allocated.
  173.      */
  174.     if (modem == NULL)
  175.         return;
  176.                     /* close the port */
  177.     if (status->fd != -1) {
  178.         ioctl(status->fd, TCFLSH, 2);
  179.         /*
  180.          * Since HUPCL is set, the close() should drop the DTR and
  181.          * hang up the modem (provided you've got the modem to
  182.          * respond to DTR).  Since this is not guaranteed, we send
  183.          * the hangup string first.
  184.          */
  185.         hang_up(verbose);
  186.         close(status->fd);
  187.     }
  188.                     /* remove the lock */
  189.     if (*status->lock_path != NULL) {
  190.         if (unlink(status->lock_path)) {
  191.             sprintf(buf, "'%s'", status->lock_path);
  192.             error_win(0, "Can't remove the lock file", buf);
  193.         }
  194.         free_ptr(status->lock_path);
  195.         status->lock_path = null_ptr;
  196.     }
  197.                     /* turn the getty back on? */
  198.     if (getty_status)
  199.         set_getty(modem->tty[modem->t_cur], 1);
  200.                     /* cleanup the structure */
  201.     status->fd = -1;
  202.     modem->m_cur = -1;
  203.     modem->t_cur = -1;
  204.     return;
  205. }
  206.  
  207. /*
  208.  * Turn the /etc/getty on or off for the specified port.  A return code
  209.  * of 1 means that the getty was on.  Systems with uugetty or dedicated
  210.  * dialout ports won't need this routine.
  211.  */
  212.  
  213. int
  214. set_getty(tty, on)
  215. char *tty;
  216. int on;
  217. {
  218. #ifdef UNIXPC
  219.     int i, ret_code;
  220.     char buf[40];
  221.     unsigned int sleep();
  222.                     /* the last three characters */
  223.     i = strlen(tty) -3;
  224.  
  225.     ret_code = 0;
  226.     if (on) {
  227.         sprintf(buf, "setgetty %s 1", tty+i);
  228.         system(buf);
  229.     }
  230.     else {
  231.         sprintf(buf, "setgetty %s 0", tty+i);
  232.         if (system(buf) == 512)
  233.             ret_code = 1;
  234.         sleep(1);
  235.     }
  236.     return(ret_code);
  237. #else /* UNIXPC */
  238.     /*
  239.      * If you don't have one of these cute little routines, you
  240.      * might wanna write one.  It should check for an existing lock
  241.      * file, edit the /etc/inittab file, and issue an init -q.
  242.      * Obviously the program would be suid to root.
  243.      */
  244.     return(0);
  245. #endif /* UNIXPC */
  246. }
  247.