+ if (inspeed == 0)
+ fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
+ }
+ baud_rate = inspeed;
+
+ if (tcsetattr(fd, TCSAFLUSH, &tios) < 0)
+ fatal("tcsetattr: %m");
+
+ restore_term = 1;
+}
+
+/*
+ * restore_tty - restore the terminal to the saved settings.
+ */
+void
+restore_tty(fd)
+ int fd;
+{
+ if (restore_term) {
+ if (!default_device) {
+ /*
+ * Turn off echoing, because otherwise we can get into
+ * a loop with the tty and the modem echoing to each other.
+ * We presume we are the sole user of this tty device, so
+ * when we close it, it will revert to its defaults anyway.
+ */
+ inittermios.c_lflag &= ~(ECHO | ECHONL);
+ }
+ if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
+ if (errno != ENXIO)
+ warn("tcsetattr: %m");
+ ioctl(fd, TIOCSWINSZ, &wsinfo);
+ restore_term = 0;
+ }
+}
+
+/*
+ * setdtr - control the DTR line on the serial port.
+ * This is called from die(), so it shouldn't call die().
+ */
+void
+setdtr(fd, on)
+int fd, on;
+{
+ int modembits = TIOCM_DTR;
+
+ ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
+}
+
+/*
+ * get_pty - get a pty master/slave pair and chown the slave side
+ * to the uid given. Assumes slave_name points to >= 12 bytes of space.
+ */
+int
+get_pty(master_fdp, slave_fdp, slave_name, uid)
+ int *master_fdp;
+ int *slave_fdp;
+ char *slave_name;
+ int uid;
+{
+ struct termios tios;
+
+ if (openpty(master_fdp, slave_fdp, slave_name, NULL, NULL) < 0)
+ return 0;
+
+ fchown(*slave_fdp, uid, -1);
+ fchmod(*slave_fdp, S_IRUSR | S_IWUSR);
+ if (tcgetattr(*slave_fdp, &tios) == 0) {
+ tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
+ tios.c_cflag |= CS8 | CREAD;
+ tios.c_iflag = IGNPAR | CLOCAL;
+ tios.c_oflag = 0;
+ tios.c_lflag = 0;
+ if (tcsetattr(*slave_fdp, TCSAFLUSH, &tios) < 0)
+ warn("couldn't set attributes on pty: %m");
+ } else
+ warn("couldn't get attributes on pty: %m");
+
+ return 1;
+}
+
+
+/*
+ * open_ppp_loopback - open the device we use for getting
+ * packets in demand mode, and connect it to a ppp interface.
+ * Here we use a pty.
+ */
+int
+open_ppp_loopback()
+{
+ int flags;
+ struct termios tios;
+ int pppdisc = PPPDISC;
+
+ if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0)
+ fatal("No free pty for loopback");
+ SYSDEBUG(("using %s for loopback", loop_name));
+
+ if (tcgetattr(loop_slave, &tios) == 0) {
+ tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
+ tios.c_cflag |= CS8 | CREAD;
+ tios.c_iflag = IGNPAR;
+ tios.c_oflag = 0;
+ tios.c_lflag = 0;
+ if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
+ warn("couldn't set attributes on loopback: %m");
+ }
+
+ if ((flags = fcntl(loop_master, F_GETFL)) != -1)
+ if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
+ warn("couldn't set loopback to nonblock: %m");
+
+ ppp_fd = loop_slave;
+ if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0)
+ fatal("ioctl(TIOCSETD): %m");
+
+ /*
+ * Find out which interface we were given.
+ */
+ if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
+ fatal("ioctl(PPPIOCGUNIT): %m");
+
+ /*
+ * Enable debug in the driver if requested.
+ */
+ if (kdebugflag) {
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
+ warn("ioctl (PPPIOCGFLAGS): %m");
+ } else {
+ flags |= (kdebugflag & 0xFF) * SC_DEBUG;
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
+ warn("ioctl(PPPIOCSFLAGS): %m");