home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / netkit-a.06 / netkit-a / NetKit-A-0.06 / dip337d-uri / tty.c < prev   
Encoding:
C/C++ Source or Header  |  1994-05-29  |  17.0 KB  |  778 lines

  1. /*
  2.  * dip        A program for handling dialup IP connecions.
  3.  *        UNIX terminal I/O support functions.  This file takes
  4.  *        care of opening, setting up and maintaining the line,
  5.  *        and it takes care of allocating the buffers and init-
  6.  *        ializing their control structures.
  7.  *
  8.  * Version:    @(#)tty.c    3.3.6    12/13/93
  9.  * Modified:    @(#)tty.c    3.3.7    05/22/94
  10.  *
  11.  * Author:      Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12.  *        Copyright 1988-1993 MicroWalt Corporation
  13.  *        Lock file stuff stolen from Taylor UUCP
  14.  *        Copyright (C) 1991, 1992 Ian Lance Taylor
  15.  *
  16.  *              Uri Blumenthal <uri@watson.ibm.com>
  17.  *              (C) 1994
  18.  *
  19.  *        This program is free software; you can redistribute it
  20.  *        and/or  modify it under  the terms of  the GNU General
  21.  *        Public  License as  published  by  the  Free  Software
  22.  *        Foundation;  either  version 2 of the License, or  (at
  23.  *        your option) any later version.
  24.  */
  25. #include "dip.h"
  26. #include <sys/stat.h>
  27. #ifdef LINUX
  28. #   include <linux/fs.h>
  29. #   include <linux/tty.h>
  30. #   include <linux/serial.h> /* for Linux-1.1.13 */
  31. #endif
  32.  
  33.  
  34. #define TTY_BUFSIZE    1024        /* size of one serial buffer    */
  35.  
  36.  
  37. static struct {
  38.   char    *speed;
  39.   int    code;
  40. } tty_speeds[] = {            /* table of usable baud rates    */
  41.   { "0",        B0      },
  42.   { "50",    B50    }, { "75",    B75      },    
  43.   { "110",    B110    }, { "300",    B300    },
  44.   { "600",    B600    }, { "1200",    B1200    },
  45.   { "2400",    B2400    }, { "4800",    B4800    },
  46.   { "9600",    B9600    },
  47. #ifdef B14400
  48.   { "14400",    B14400    },
  49. #endif
  50. #ifdef B19200
  51.   { "19200",    B19200    },
  52. #endif
  53. #ifdef B38400
  54.   { "38400",    B38400    },
  55. #endif
  56. #ifdef B57600
  57.   { "57600",    B57600    },
  58. #endif
  59. #ifdef B115200
  60.   { "115200",    B115200    },
  61. #endif
  62.   { NULL,    0    }
  63. };
  64.  
  65.  
  66. static struct termios    tty_saved;    /* saved TTY device state    */
  67.  
  68. static struct termios   tty_current;    /* current TTY device state    */
  69.  
  70. static char        *in_buff,    /* line input/output buffers    */
  71.             *out_buff,
  72.             *in_ptr,
  73.             *out_ptr;
  74.  
  75. static int        in_size,    /* buffer sizes and counters    */
  76.             out_size,
  77.             in_cnt,
  78.             out_cnt,
  79.             tty_sdisc,    /* saved TTY line discipline    */
  80.             tty_ldisc,    /* current TTY line discipline    */
  81.             tty_fd = -1;    /* TTY file descriptor        */
  82.  
  83.  
  84. /* Disable any messages to the input channel of this process. */
  85. int
  86. tty_nomesg(void)
  87. {
  88.   return(fchmod(0, 0600));
  89. }
  90.  
  91.  
  92. /* Lock or unlock a terminal line. */
  93. int
  94. tty_lock(char *path, int mode)
  95. {
  96.   static char saved_path[PATH_MAX];
  97.   static int saved_lock = 0;
  98.   struct passwd *pw;
  99. #if !defined(linux)
  100. #if HAVE_V2_LOCKFILES
  101.   int i;
  102. #else
  103.   char ab[12];
  104. #endif
  105.   int fd;
  106.   pid_t ime;
  107.   int cwrote;
  108. #endif
  109.  
  110.  
  111.   if (mode == 1) {    /* lock */
  112.     if (path == NULL) return(0);    /* standard input */
  113.     sprintf(saved_path, "%s/LCK..%s", _PATH_LOCKD, path);
  114. #if 0
  115.     if ((fd = creat(saved_path, 0644)) < 0) {
  116.       if (errno != EEXIST)
  117.     fprintf(stderr, "DIP: tty: lock: (%s): %s\n",
  118.         saved_path, strerror(errno));
  119.       return(-1);
  120.     }
  121.     ime = getpid ();
  122. #if HAVE_V2_LOCKFILES
  123.     i = ime;
  124.     cwrote = write (fd, &i, sizeof i);
  125. #else
  126.     sprintf (ab, "%10d\n", (int) ime);
  127.     cwrote = write (fd, ab, strlen (ab));
  128. #endif
  129.     (void) close(fd);
  130. #else
  131.     {
  132.       FILE *fd;
  133.       if ((fd = fopen(saved_path, "w")) == (FILE *)0) {
  134.     syslog(LOG_ERR, "DIP: tty: lock: (%s): %s\n",
  135.            saved_path, strerror(errno));
  136.     fprintf(stderr, "DIP: tty: lock: (%s): %s\n",
  137.         saved_path, strerror(errno));
  138.     return(-1);
  139.       }
  140.       fprintf(fd, "%10d\n", (int)getpid());
  141.       (void)fclose(fd);
  142.     }
  143. #endif
  144.     
  145.     /* Make sure UUCP owns the lockfile.  Required by some packages. */
  146.     if ((pw = getpwnam(_UID_UUCP)) == NULL) {
  147.       fprintf(stderr, "DIP: tty: lock: UUCP user %s unknown!\n",
  148.           _UID_UUCP);
  149.       return(0);    /* keep the lock anyway */
  150.     }
  151.     (void) chown(saved_path, pw->pw_uid, pw->pw_gid);
  152.     saved_lock = 1;
  153.   } else {
  154.     if (mode == 2) { /* re-acquire a lock after a fork() */
  155.       FILE *fd;
  156.       
  157.       if (saved_lock != 1) {
  158.     syslog(LOG_ERR, 
  159.            "DIP: tty_lock reaquire: lock was not saved!\n");
  160.     return (-1);
  161.       }
  162.       if ((fd = fopen(saved_path, "w")) == (FILE *)0) {
  163.     syslog(LOG_ERR, "DIP:tty_lock(%s) reaquire: %s\n",
  164.            saved_path, strerror(errno));
  165.     fprintf(stderr, "DIP:fork: tty: lock: (%s): %s\n",
  166.         saved_path, strerror(errno));
  167.     return(-1);
  168.       }
  169.       fprintf(fd, "%10d\n", (int)getpid());
  170.       (void)fclose(fd);
  171.       return(0);
  172.     } else {    /* unlock */
  173.       FILE *fd;
  174.       
  175.       if (saved_lock != 1) {
  176.     syslog(LOG_ERR, "DIP:tty_lock: lock was not saved?!\n");
  177.     return(0);
  178.       }
  179.       if ((fd = fopen(saved_path, "w")) == (FILE *)0) {
  180.     syslog(LOG_ERR, "DIP:tty_lock: can't reopen to delete: %s\n",
  181.            strerror(errno));
  182.     return (-1);
  183.       }
  184.       if (unlink(saved_path) < 0) {
  185.     syslog(LOG_ERR, "DIP: tty: unlock: (%s): %s\n", saved_path,
  186.            strerror(errno));
  187.     fprintf(stderr, "DIP: tty: unlock: (%s): %s\n", saved_path,
  188.         strerror(errno));
  189.     saved_lock = 0;
  190.     return(-1);
  191.       }
  192.       saved_lock = 0;
  193.     }
  194.   }
  195.   
  196.   return(0);
  197. }
  198.  
  199.  
  200. /* Find a serial speed code in the table. */
  201. static int
  202. tty_find_speed(char *speed)
  203. {
  204.   int i;
  205.  
  206.   i = 0;
  207.   while (tty_speeds[i].speed != NULL) {
  208.     if (! strcmp(tty_speeds[i].speed, speed)) return(tty_speeds[i].code);
  209.     i++;
  210.   }
  211.   return(-EINVAL);
  212. }
  213.  
  214.  
  215. /* Set the number of stop bits. */
  216. static int
  217. tty_set_stopbits(struct termios *tty, char *stopbits)
  218. {
  219.   if (opt_v) printf("DIP: tty: set_stopbits: %c\n", *stopbits);
  220.   switch(*stopbits) {
  221.     case '1':
  222.         tty->c_cflag &= ~CSTOPB;
  223.         break;
  224.  
  225.     case '2':
  226.         tty->c_cflag |= CSTOPB;
  227.         break;
  228.  
  229.     default:
  230.         return(-EINVAL);
  231.   }
  232.   return(0);
  233. }
  234.  
  235.  
  236. /* Set the number of data bits. */
  237. static int
  238. tty_set_databits(struct termios *tty, char *databits)
  239. {
  240.   if (opt_v) printf("DIP: tty: set_databits: %c\n", *databits);
  241.   tty->c_cflag &= ~CSIZE;
  242.   switch(*databits) {
  243.     case '5':
  244.         tty->c_cflag |= CS5;
  245.         break;
  246.  
  247.     case '6':
  248.         tty->c_cflag |= CS6;
  249.         break;
  250.  
  251.     case '7':
  252.         tty->c_cflag |= CS7;
  253.         break;
  254.  
  255.     case '8':
  256.         tty->c_cflag |= CS8;
  257.         break;
  258.  
  259.     default:
  260.         return(-EINVAL);
  261.   }
  262.   return(0);
  263. }
  264.  
  265.  
  266. /* Set the type of parity encoding. */
  267. static int
  268. tty_set_parity(struct termios *tty, char *parity)
  269. {
  270.   if (opt_v) printf("DIP: tty: set_parity: %c\n", *parity);
  271.   switch(toupper(*parity)) {
  272.     case 'N':
  273.         tty->c_cflag &= ~(PARENB | PARODD);
  274.         break;  
  275.  
  276.     case 'O':
  277.         tty->c_cflag &= ~(PARENB | PARODD);
  278.         tty->c_cflag |= (PARENB | PARODD);
  279.         break;
  280.  
  281.     case 'E':
  282.         tty->c_cflag &= ~(PARENB | PARODD);
  283.         tty->c_cflag |= (PARENB);
  284.         break;
  285.  
  286.     default:
  287.         return(-EINVAL);
  288.   }
  289.   return(0);
  290. }
  291.  
  292.  
  293. /* Set the line speed of a terminal line. */
  294. static int
  295. tty_set_speed(struct termios *tty, char *speed)
  296. {
  297.   int code;
  298.  
  299.   if (opt_v) printf("DIP: tty: set_speed: %s\n", speed);
  300.   code = tty_find_speed(speed);
  301.   if (code < 0) return(-1);
  302.   tty->c_cflag &= ~CBAUD;
  303.   tty->c_cflag |= code;
  304.  
  305.   return(0);
  306. }
  307.  
  308.  
  309. /* Put a terminal line in a transparent state. */
  310. static int
  311. tty_set_raw(struct termios *tty)
  312. {
  313.   int i;
  314.   int speed;
  315.  
  316.   for(i = 0; i < NCCS; i++)
  317.         tty->c_cc[i] = '\0';        /* no spec chr        */
  318.   tty->c_cc[VMIN] = 1;
  319.   tty->c_cc[VTIME] = 0;
  320.   tty->c_iflag = (IGNBRK | IGNPAR);        /* input flags        */
  321.   tty->c_oflag = (0);                /* output flags        */
  322.   tty->c_lflag = (0);                /* local flags        */
  323.   speed = (tty->c_cflag & CBAUD);        /* save current speed    */
  324.   tty->c_cflag = (CRTSCTS|HUPCL|CREAD|CLOCAL);    /* UART flags        */
  325.   tty->c_cflag |= speed;            /* restore speed    */
  326.   return(0);
  327. }
  328.  
  329.  
  330. /* Fetch the state of a terminal. */
  331. static int
  332. tty_get_state(struct termios *tty)
  333. {
  334.   if (ioctl(tty_fd, TCGETS, tty) < 0) {
  335.     syslog(LOG_ERR, "DIP: tty: get_state: %s\n", strerror(errno));
  336.     fprintf(stderr, "DIP: tty: get_state: %s\n", strerror(errno));
  337.     return(-errno);
  338.   }
  339.   return(0);
  340. }
  341.  
  342.  
  343. /* Set the state of a terminal. */
  344. static int
  345. tty_set_state(struct termios *tty)
  346. {
  347.   
  348.   if (ioctl(tty_fd, TCSETS, tty) < 0) {
  349.     syslog(LOG_ERR, "DIP: tty: set_state: %s\n", strerror(errno));
  350.     fprintf(stderr, "DIP: tty: set_state: %s\n", strerror(errno));
  351.     return(-errno);
  352.   }
  353.   return(0);
  354. }
  355.  
  356.  
  357. /* Get the line discipline of a terminal line. */
  358. int
  359. tty_get_disc(int *disc)
  360. {
  361.   if (ioctl(tty_fd, TIOCGETD, disc) < 0) {
  362.     syslog(LOG_ERR, "DIP: tty: get_disc: %s\n", strerror(errno));
  363.     fprintf(stderr, "DIP: tty: get_disc: %s\n", strerror(errno));
  364.     return(-errno);
  365.   }
  366.   return(0);
  367. }
  368.  
  369.  
  370. /* Set the line discipline of a terminal line. */
  371. int
  372. tty_set_disc(int disc)
  373. {
  374.  
  375.   if (disc == -1) disc = tty_sdisc;
  376.  
  377.   if (ioctl(tty_fd, TIOCSETD, &disc) < 0) {
  378.     syslog(LOG_ERR, "DIP: tty: set_disc(%d): %s\n", disc, strerror(errno));
  379.     fprintf(stderr, "DIP: tty: set_disc(%d): %s\n", disc, strerror(errno));
  380.     return(-errno);
  381.   }
  382.   return(0);
  383. }
  384.  
  385.  
  386. /* Get the encapsulation type of a terminal line. */
  387. int
  388. tty_get_encap(int *encap)
  389. {
  390.   if (ioctl(tty_fd, SIOCGIFENCAP, encap) < 0) {
  391.     syslog(LOG_ERR, "DIP: tty: get_encap: %s\n", strerror(errno));
  392.     fprintf(stderr, "DIP: tty: get_encap: %s\n", strerror(errno));
  393.     return(-errno);
  394.   }
  395.   return(0);
  396. }
  397.  
  398.  
  399. /* Set the encapsulation type of a terminal line. */
  400. int
  401. tty_set_encap(int encap)
  402. {
  403.   if (ioctl(tty_fd, SIOCSIFENCAP, &encap) < 0) {
  404.     fprintf(stderr, "DIP: tty: set_encap(%d): %s\n",
  405.                     encap, strerror(errno));
  406.     return(-errno);
  407.   }
  408.   return(0);
  409. }
  410.  
  411.  
  412. /* Fetch the name of the network interface attached to this terminal. */
  413. int
  414. tty_get_name(char *name)
  415. {
  416.   if (ioctl(tty_fd, SIOCGIFNAME, name) < 0) {
  417.     syslog(LOG_ERR, "DIP: tty_get_name: %s\n", strerror(errno));
  418.     fprintf(stderr, "DIP: tty_get_name: %s\n", strerror(errno));
  419.     return(-errno);
  420.   }
  421.   return(0);
  422. }
  423.  
  424.  
  425. /* Read one character (byte) from the TTY link. */
  426. int
  427. tty_getc(void)
  428. {
  429.   int s;
  430.  
  431.   if (in_cnt <= 0) {
  432.     s = read(tty_fd, in_buff, in_size);
  433.     in_cnt = s;
  434.     in_ptr = in_buff;
  435.   }
  436.  
  437.   if (in_cnt < 0) {
  438.     if (opt_v == 1) printf("DIP: tty: getc: I/O error.\n");
  439.     return(-1);
  440.   }
  441.  
  442.   s = (int) *in_ptr;
  443.   s &= 0xFF;
  444.   in_ptr++;
  445.   in_cnt--;
  446.   return(s);
  447. }
  448.  
  449.  
  450. /* Write one character (byte) to the TTY link. */
  451. int
  452. tty_putc(int c)
  453. {
  454.   int s;
  455.  
  456.   if ((out_cnt == out_size) || (c == -1)) {
  457.     s = write(tty_fd, out_buff, out_cnt);
  458.     out_cnt = 0;
  459.     out_ptr = out_buff;
  460.     if (s < 0) return(-1);
  461.   }
  462.   
  463.   if (c != -1) {
  464.     *out_ptr = (char) c;
  465.     out_ptr++;
  466.     out_cnt++;
  467.   }
  468.   
  469.   return(0);
  470. }
  471.  
  472.  
  473. /* Output a string of characters to the TTY link. */
  474. void
  475. tty_puts(char *s)
  476. {
  477.   while(*s != '\0') tty_putc((int) *s++);
  478.   tty_putc(-1);    /* flush */
  479. }
  480.  
  481.  
  482. /* Return the TTY link's file descriptor. */
  483. int
  484. tty_askfd(void)
  485. {
  486.   return(tty_fd);
  487. }
  488.  
  489.  
  490. /* Set the number of databits a terminal line. */
  491. int
  492. tty_databits(char *bits)
  493. {
  494.   if (tty_set_databits(&tty_current, bits) < 0) return(-1);
  495.   return(tty_set_state(&tty_current));
  496. }
  497.  
  498.  
  499. /* Set the number of stopbits of a terminal line. */
  500. int
  501. tty_stopbits(char *bits)
  502. {
  503.   if (tty_set_stopbits(&tty_current, bits) < 0) return(-1);
  504.   return(tty_set_state(&tty_current));
  505. }
  506.  
  507.  
  508. /* Set the type of parity of a terminal line. */
  509. int
  510. tty_parity(char *type)
  511. {
  512.   if (tty_set_parity(&tty_current, type) < 0) return(-1);
  513.   return(tty_set_state(&tty_current));
  514. }
  515.  
  516.  
  517. /* Set the line speed of a terminal line. */
  518. int
  519. tty_speed(char *speed)
  520. {
  521. #if defined(LINUX)
  522.   struct serial_struct info;
  523.   int spd;
  524.  
  525.   spd = atoi(speed);
  526.   if (ioctl(tty_fd, TIOCGSERIAL, &info)) return(-1);
  527.   info.flags = info.flags & ~ASYNC_SPD_MASK;
  528.  
  529.   if (spd == 115200) {
  530.           if (tty_set_speed(&tty_current, "38400") < 0) return(-1);
  531.           info.flags |= ASYNC_SPD_VHI;
  532.   } else if (spd == 57600) {
  533.           if (tty_set_speed(&tty_current, "38400") < 0) return(-1);
  534.           info.flags |= ASYNC_SPD_HI;
  535.   } else {
  536.       if (tty_set_speed(&tty_current, speed) < 0) return(-1);
  537.   }
  538.   if (ioctl(tty_fd, TIOCSSERIAL, &info)) return(-1);
  539. #else
  540.   if (tty_set_speed(&tty_current, speed) < 0) return(-1);
  541. #endif
  542.  
  543.   return(tty_set_state(&tty_current));
  544. }
  545.  
  546.  
  547. /* Hangup the line. */
  548. int
  549. hanguptty(void)
  550. {
  551.   struct termios tty;
  552.  
  553.   tty = tty_current;
  554.   (void) tty_set_speed(&tty, "0");
  555.   if (tty_set_state(&tty) < 0) {
  556.     syslog(LOG_ERR, "DIP: tty: hangup(DROP): %s\n", strerror(errno));
  557.     fprintf(stderr, "DIP: tty: hangup(DROP): %s\n", strerror(errno));
  558.     return(-errno);
  559.   }
  560.   
  561.   (void) sleep(3);
  562.   
  563.   if (tty_set_state(&tty_current) < 0) {
  564.     syslog(LOG_ERR, "DIP: tty: hangup(RAISE): %s\n", strerror(errno));
  565.     fprintf(stderr, "DIP: tty: hangup(RAISE): %s\n", strerror(errno));
  566.     return(-errno);
  567.   }
  568.   return(0);
  569. }
  570.  
  571. /* Clear the CLOCAL bit. (detect carrier loss) */
  572. int
  573. tty_notlocal(void)
  574. {
  575.   /* Release any control terminal we might have. */
  576.   if (setsid() < 0) {
  577.     syslog(LOG_ERR, 
  578.        "DIP: tty_notlocal cannot setsid: %s\n", strerror(errno));
  579.     fprintf(stderr, 
  580.         "DIP: tty_notlocal cannot setsid: %s\n", strerror(errno));
  581.   }
  582.  
  583.   if (opt_v) {
  584.     char ch0[20];
  585.     char ch1[20];
  586.  
  587.     strcpy(ch0, ttyname(0));
  588.     strcpy(ch1, ttyname(tty_fd));
  589.     syslog(LOG_ERR, "tty_notlocal: fd0: %s  fd%1d %s\n", ch0, tty_fd, ch1);
  590.   }
  591.  
  592. #if 1 /* don't know why... What's wrong with it?! */
  593.   if (ioctl(tty_fd, TIOCSCTTY, 1) < 0) {
  594.     syslog(LOG_ERR, 
  595.        "DIP: tty_notlocal cannot TIOCSCTTY: %s\n", strerror(errno));
  596.     fprintf(stderr, 
  597.         "DIP: tty_notlocal cannot TIOCSCTTY: %s\n", strerror(errno));
  598.   }
  599. #endif
  600.   tty_current.c_cflag &= ~CLOCAL;
  601.   if (tty_set_state(&tty_current) < 0) {
  602.     syslog(LOG_ERR, 
  603.        "DIP: tty_notlocal cannot clr CLOCAL: %s\n", strerror(errno));
  604.     fprintf(stderr, 
  605.         "DIP: tty_notlocal cannot clr CLOCAL: %s\n", strerror(errno));
  606.     return(-errno);
  607.   }
  608.   return(0);
  609. }
  610.  
  611. int tty_login(void)
  612. {
  613.   if (ioctl(tty_fd, TIOCSCTTY, 1) < 0)
  614.     syslog(LOG_ERR, 
  615.        "DIP: tty_login cannot TIOCSCTTY: %s\n", strerror(errno));  
  616.   tty_current.c_cflag &= ~CLOCAL;
  617.   if (tty_set_state(&tty_current) < 0)
  618.     syslog(LOG_ERR, 
  619.        "DIP: tty_notlocal cannot clr CLOCAL: %s\n", strerror(errno));
  620.   return 0;
  621. } /* tty_login() */
  622.  
  623.  
  624. /* Flush input on the terminal. */
  625. int
  626. tty_flush(void)
  627. {
  628.   int blkmode;
  629.   char buf;
  630.  
  631.   blkmode = fcntl(tty_fd, F_GETFL, NULL);
  632.   fcntl(tty_fd, F_SETFL, (O_NDELAY | blkmode));
  633.   while (read(tty_fd, &buf, 1) > 0)
  634.         ;
  635.   fcntl(tty_fd, F_SETFL, blkmode);
  636.   return(0);
  637. }
  638.  
  639.  
  640. /* Close down a terminal line. */
  641. int
  642. tty_close(void)
  643. {
  644.   (void) tty_set_disc(tty_sdisc);
  645.   
  646.   if (tty_set_state(&tty_saved) < 0) {
  647.     syslog(LOG_ERR, "DIP: tty:tcsetattr(tty_saved): %s\n", 
  648.            strerror(errno));
  649.     fprintf(stderr, "DIP: tty: restore: %s\n", strerror(errno));
  650.     (void) tty_lock("no_diff", 0);
  651.     return(-errno);
  652.   }
  653.  
  654.   (void) tty_lock("dont_care", 0);
  655.   (void) hanguptty();
  656.   (void) mdm_hangup();
  657.  
  658.   return(0);
  659. }
  660.  
  661.  
  662. int tty_login_close(void)
  663. {
  664. #if 0
  665.   char ifname[32];
  666.  
  667.   (void) tty_get_name(ifname);
  668.   (void) detach(ifname);
  669.  
  670.   (void) tty_set_disc(tty_sdisc);
  671.  
  672.   if (tcsetattr(tty_fd, TCSAFLUSH, &tty_saved) < 0)
  673.     syslog(LOG_ERR, "DIP: tty_login_close:tcsetattr(tty_saved): %s\n",
  674.        strerror(errno));
  675. #endif
  676.   (void) mdm_hangup();
  677.  
  678.   return 0;
  679. }
  680.  
  681.  
  682. /* Open and initialize a terminal line. */
  683. int
  684. tty_open(char *name)
  685. {
  686.   char path[PATH_MAX];
  687.   register char *sp;
  688.   int fd,flags;
  689.  
  690.   /* Try opening the TTY device. */
  691.   if (name != NULL) {
  692.     if ((sp = strrchr(name, '/')) != (char *)NULL) *sp++ = '\0';
  693.       else sp = name;
  694.     sprintf(path, "/dev/%s", sp);
  695.     if ((fd = open(path, O_RDWR|O_NDELAY)) < 0) {
  696.         fprintf(stderr, "DIP: tty: open(%s, RW): %s\n",
  697.                         path, strerror(errno));
  698.         return(-errno);
  699.     }
  700.     tty_fd = fd;
  701.     if (opt_v) {
  702.       printf("DIP: tty: open: %s (%d) ", path, fd);
  703.       syslog(LOG_INFO, "DIP: tty: open: %s (%d) ", path, fd);
  704.     }
  705.   } else {
  706.     tty_fd = 0;
  707.     sp = (char *)NULL;
  708.   }
  709.  
  710.   if(tty_lock(sp, 1)) {
  711.     fprintf(stderr, "DIP: problems with locking %s\n",
  712.         sp);
  713.     return (-1);
  714.   }
  715.  
  716.   /* Size and allocate the I/O buffers. */
  717.   in_size = TTY_BUFSIZE;
  718.   out_size = in_size;
  719.   in_buff = (char *) malloc(in_size);
  720.   out_buff = (char *) malloc(out_size);
  721.   if (in_buff == (char *)NULL || out_buff == (char *)NULL) {
  722.     fprintf(stderr, "DIP: tty: open: cannot alloc(%d, %d) buffers (%d)\n",
  723.                         in_size, out_size, errno);
  724.     return(-ENOMEM);
  725.   }
  726.   in_cnt = 0;
  727.   out_cnt = 0;
  728.   in_ptr = in_buff;
  729.   out_ptr = out_buff;
  730.   out_size -= 4; /* safety */
  731.   if (opt_v) printf("DIP: tty: open: IBUF=%d OBUF=%d\n", in_size, out_size);
  732.  
  733.   /* Fetch the current state of the terminal. */
  734.   if (tty_get_state(&tty_saved) < 0) {
  735.     fprintf(stderr, "DIP: tty: open: cannot get current state!\n");
  736.     return(-errno);
  737.   }
  738.   
  739.   (void) memcpy ((char *)&tty_current,
  740.       (char *)&tty_saved, sizeof(struct termios));
  741.  
  742.   /* Fetch the current line discipline of this terminal. */
  743.   if (tty_get_disc(&tty_sdisc) < 0) {
  744.     fprintf(stderr, "DIP: tty: open: cannot get current line disc!\n");
  745.     return(-errno);
  746.   } 
  747.   tty_ldisc = tty_sdisc;
  748.  
  749.   /* Put this terminal line in a 8-bit transparent mode. */
  750.   if (tty_set_raw(&tty_current) < 0) {
  751.     fprintf(stderr, "DIP: tty: open: cannot set RAW mode!\n");
  752.     return(-errno);
  753.   }
  754.  
  755.   /* If we are running in MASTER mode, set the default speed. */
  756.   if ((name != NULL) && (tty_set_speed(&tty_current, "38400") != 0)) {
  757.     fprintf(stderr, "DIP: tty: open: cannot set 38400 bps!\n");
  758.     return(-errno);
  759.   }
  760.  
  761.   /* Set up a completely 8-bit clean line. */
  762.   if (tty_set_databits(&tty_current, "8") ||
  763.       tty_set_stopbits(&tty_current, "1") ||
  764.       tty_set_parity(&tty_current, "N")) {
  765.     fprintf(stderr, "DIP: tty: open: cannot set 8N1 mode!\n");
  766.     return(-errno);
  767.   }
  768.  
  769.   /* Set the new line mode. */
  770.   if ((fd = tty_set_state(&tty_current)) < 0) return(fd);
  771.   /* Clear the NDELAY flag now (line is in CLOCAL) */
  772.   flags = fcntl(tty_fd, F_GETFL, 0);
  773.   fcntl(tty_fd, F_SETFL, flags & ~O_NDELAY);
  774.  
  775.   /* OK, all done.  Lock this terminal line. */
  776.   return(0);
  777. }
  778.