xref: /freebsd/usr.sbin/ppp/tty.c (revision d0b3b745)
15d9e6103SBrian Somers /*-
25d9e6103SBrian Somers  * Copyright (c) 1999 Brian Somers <brian@Awfulhak.org>
35d9e6103SBrian Somers  * All rights reserved.
45d9e6103SBrian Somers  *
55d9e6103SBrian Somers  * Redistribution and use in source and binary forms, with or without
65d9e6103SBrian Somers  * modification, are permitted provided that the following conditions
75d9e6103SBrian Somers  * are met:
85d9e6103SBrian Somers  * 1. Redistributions of source code must retain the above copyright
95d9e6103SBrian Somers  *    notice, this list of conditions and the following disclaimer.
105d9e6103SBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
115d9e6103SBrian Somers  *    notice, this list of conditions and the following disclaimer in the
125d9e6103SBrian Somers  *    documentation and/or other materials provided with the distribution.
135d9e6103SBrian Somers  *
145d9e6103SBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
155d9e6103SBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165d9e6103SBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
175d9e6103SBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
185d9e6103SBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
195d9e6103SBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
205d9e6103SBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
215d9e6103SBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
225d9e6103SBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
235d9e6103SBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
245d9e6103SBrian Somers  * SUCH DAMAGE.
255d9e6103SBrian Somers  *
26d0b3b745SBrian Somers  *	$Id: tty.c,v 1.7 1999/05/24 16:39:16 brian Exp $
275d9e6103SBrian Somers  */
285d9e6103SBrian Somers 
295d9e6103SBrian Somers #include <sys/param.h>
305d9e6103SBrian Somers #include <sys/socket.h>
315d9e6103SBrian Somers #include <netinet/in.h>
325d9e6103SBrian Somers #include <arpa/inet.h>
335d9e6103SBrian Somers #include <netdb.h>
345d9e6103SBrian Somers #include <netinet/in_systm.h>
355d9e6103SBrian Somers #include <netinet/ip.h>
365d9e6103SBrian Somers #include <sys/un.h>
375d9e6103SBrian Somers #if defined(__OpenBSD__) || defined(__NetBSD__)
385d9e6103SBrian Somers #include <sys/ioctl.h>
395d9e6103SBrian Somers #include <util.h>
405d9e6103SBrian Somers #else
415d9e6103SBrian Somers #include <libutil.h>
425d9e6103SBrian Somers #endif
435d9e6103SBrian Somers 
445d9e6103SBrian Somers #include <errno.h>
455d9e6103SBrian Somers #include <fcntl.h>
465d9e6103SBrian Somers #include <paths.h>
475d9e6103SBrian Somers #include <stdio.h>
485d9e6103SBrian Somers #include <stdlib.h>
495d9e6103SBrian Somers #include <string.h>
505d9e6103SBrian Somers #include <sys/wait.h>
516815097bSBrian Somers #include <sys/uio.h>
525d9e6103SBrian Somers #include <termios.h>
535d9e6103SBrian Somers #include <unistd.h>
545d9e6103SBrian Somers 
555d9e6103SBrian Somers #include "layer.h"
565d9e6103SBrian Somers #include "defs.h"
575d9e6103SBrian Somers #include "mbuf.h"
585d9e6103SBrian Somers #include "log.h"
595d9e6103SBrian Somers #include "id.h"
605d9e6103SBrian Somers #include "sync.h"
615d9e6103SBrian Somers #include "timer.h"
625d9e6103SBrian Somers #include "lqr.h"
635d9e6103SBrian Somers #include "hdlc.h"
645d9e6103SBrian Somers #include "throughput.h"
655d9e6103SBrian Somers #include "fsm.h"
665d9e6103SBrian Somers #include "lcp.h"
675d9e6103SBrian Somers #include "ccp.h"
685d9e6103SBrian Somers #include "link.h"
695d9e6103SBrian Somers #include "async.h"
705d9e6103SBrian Somers #include "slcompress.h"
715d9e6103SBrian Somers #include "iplist.h"
725d9e6103SBrian Somers #include "ipcp.h"
735d9e6103SBrian Somers #include "filter.h"
745d9e6103SBrian Somers #include "descriptor.h"
755d9e6103SBrian Somers #include "physical.h"
765d9e6103SBrian Somers #include "mp.h"
775d9e6103SBrian Somers #ifndef NORADIUS
785d9e6103SBrian Somers #include "radius.h"
795d9e6103SBrian Somers #endif
805d9e6103SBrian Somers #include "chat.h"
815d9e6103SBrian Somers #include "command.h"
825d9e6103SBrian Somers #include "bundle.h"
835d9e6103SBrian Somers #include "prompt.h"
845d9e6103SBrian Somers #include "auth.h"
855d9e6103SBrian Somers #include "chap.h"
865d9e6103SBrian Somers #include "cbcp.h"
875d9e6103SBrian Somers #include "datalink.h"
885d9e6103SBrian Somers #include "tty.h"
895d9e6103SBrian Somers 
906815097bSBrian Somers #define	Online(dev)	((dev)->mbits & TIOCM_CD)
916815097bSBrian Somers 
926815097bSBrian Somers struct ttydevice {
936815097bSBrian Somers   struct device dev;		/* What struct physical knows about */
946815097bSBrian Somers   struct pppTimer Timer;	/* CD checks */
956815097bSBrian Somers   int mbits;			/* Current DCD status */
966815097bSBrian Somers   struct termios ios;		/* To be able to reset from raw mode */
976815097bSBrian Somers };
986815097bSBrian Somers 
996815097bSBrian Somers #define device2tty(d) ((d)->type == TTY_DEVICE ? (struct ttydevice *)d : NULL)
1005d9e6103SBrian Somers 
1015d9e6103SBrian Somers /*
1025d9e6103SBrian Somers  * tty_Timeout() watches the DCD signal and mentions it if it's status
1035d9e6103SBrian Somers  * changes.
1045d9e6103SBrian Somers  */
1055d9e6103SBrian Somers static void
1065d9e6103SBrian Somers tty_Timeout(void *data)
1075d9e6103SBrian Somers {
1085d9e6103SBrian Somers   struct physical *p = data;
1096815097bSBrian Somers   struct ttydevice *dev = device2tty(p->handler);
1105d9e6103SBrian Somers   int ombits, change;
1115d9e6103SBrian Somers 
1126815097bSBrian Somers   timer_Stop(&dev->Timer);
1136815097bSBrian Somers   dev->Timer.load = SECTICKS;		/* Once a second please */
1146815097bSBrian Somers   timer_Start(&dev->Timer);
1156815097bSBrian Somers   ombits = dev->mbits;
1165d9e6103SBrian Somers 
1175d9e6103SBrian Somers   if (p->fd >= 0) {
1186815097bSBrian Somers     if (ioctl(p->fd, TIOCMGET, &dev->mbits) < 0) {
1195d9e6103SBrian Somers       log_Printf(LogPHASE, "%s: ioctl error (%s)!\n", p->link.name,
1205d9e6103SBrian Somers                  strerror(errno));
1215d9e6103SBrian Somers       datalink_Down(p->dl, CLOSE_NORMAL);
1226815097bSBrian Somers       timer_Stop(&dev->Timer);
1235d9e6103SBrian Somers       return;
1245d9e6103SBrian Somers     }
1255d9e6103SBrian Somers   } else
1266815097bSBrian Somers     dev->mbits = 0;
1275d9e6103SBrian Somers 
1285d9e6103SBrian Somers   if (ombits == -1) {
1295d9e6103SBrian Somers     /* First time looking for carrier */
1306815097bSBrian Somers     if (Online(dev))
1315d9e6103SBrian Somers       log_Printf(LogDEBUG, "%s: %s: CD detected\n", p->link.name, p->name.full);
1325d9e6103SBrian Somers     else if (p->cfg.cd.required) {
1335d9e6103SBrian Somers       log_Printf(LogPHASE, "%s: %s: Required CD not detected\n",
1345d9e6103SBrian Somers                  p->link.name, p->name.full);
1355d9e6103SBrian Somers       datalink_Down(p->dl, CLOSE_NORMAL);
1365d9e6103SBrian Somers     } else {
1375d9e6103SBrian Somers       log_Printf(LogPHASE, "%s: %s doesn't support CD\n",
1385d9e6103SBrian Somers                  p->link.name, p->name.full);
1396815097bSBrian Somers       timer_Stop(&dev->Timer);
1406815097bSBrian Somers       dev->mbits = TIOCM_CD;
1415d9e6103SBrian Somers     }
1425d9e6103SBrian Somers   } else {
1436815097bSBrian Somers     change = ombits ^ dev->mbits;
1445d9e6103SBrian Somers     if (change & TIOCM_CD) {
1456815097bSBrian Somers       if (dev->mbits & TIOCM_CD)
1465d9e6103SBrian Somers         log_Printf(LogDEBUG, "%s: offline -> online\n", p->link.name);
1475d9e6103SBrian Somers       else {
1485d9e6103SBrian Somers         log_Printf(LogDEBUG, "%s: online -> offline\n", p->link.name);
1495d9e6103SBrian Somers         log_Printf(LogPHASE, "%s: Carrier lost\n", p->link.name);
1505d9e6103SBrian Somers         datalink_Down(p->dl, CLOSE_NORMAL);
1516815097bSBrian Somers         timer_Stop(&dev->Timer);
1525d9e6103SBrian Somers       }
1535d9e6103SBrian Somers     } else
1545d9e6103SBrian Somers       log_Printf(LogDEBUG, "%s: Still %sline\n", p->link.name,
1556815097bSBrian Somers                  Online(dev) ? "on" : "off");
1565d9e6103SBrian Somers   }
1575d9e6103SBrian Somers }
1585d9e6103SBrian Somers 
1595d9e6103SBrian Somers static void
1605d9e6103SBrian Somers tty_StartTimer(struct physical *p)
1615d9e6103SBrian Somers {
1626815097bSBrian Somers   struct ttydevice *dev = device2tty(p->handler);
1636815097bSBrian Somers 
1646815097bSBrian Somers   timer_Stop(&dev->Timer);
1656815097bSBrian Somers   dev->Timer.load = SECTICKS * p->cfg.cd.delay;
1666815097bSBrian Somers   dev->Timer.func = tty_Timeout;
1676815097bSBrian Somers   dev->Timer.name = "tty CD";
1686815097bSBrian Somers   dev->Timer.arg = p;
1695d9e6103SBrian Somers   log_Printf(LogDEBUG, "%s: Using tty_Timeout [%p]\n",
1705d9e6103SBrian Somers              p->link.name, tty_Timeout);
1716815097bSBrian Somers   dev->mbits = -1;		/* So we know it's the first time */
1726815097bSBrian Somers   timer_Start(&dev->Timer);
1735d9e6103SBrian Somers }
1745d9e6103SBrian Somers 
1755d9e6103SBrian Somers static int
1765d9e6103SBrian Somers tty_Raw(struct physical *p)
1775d9e6103SBrian Somers {
1786815097bSBrian Somers   struct ttydevice *dev = device2tty(p->handler);
1798dbb1e2bSBrian Somers   struct termios ios;
1805d9e6103SBrian Somers   int oldflag;
1815d9e6103SBrian Somers 
1825d9e6103SBrian Somers   if (physical_IsSync(p))
1835d9e6103SBrian Somers     return 1;
1845d9e6103SBrian Somers 
1855d9e6103SBrian Somers   log_Printf(LogDEBUG, "%s: Entering physical_Raw\n", p->link.name);
1865d9e6103SBrian Somers 
1876815097bSBrian Somers   if (p->type != PHYS_DIRECT && p->fd >= 0 && !Online(dev))
1885d9e6103SBrian Somers     log_Printf(LogDEBUG, "%s: Raw: descriptor = %d, mbits = %x\n",
1896815097bSBrian Somers               p->link.name, p->fd, dev->mbits);
1905d9e6103SBrian Somers 
1918dbb1e2bSBrian Somers   tcgetattr(p->fd, &ios);
1928dbb1e2bSBrian Somers   cfmakeraw(&ios);
1935d9e6103SBrian Somers   if (p->cfg.rts_cts)
1948dbb1e2bSBrian Somers     ios.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW;
1955d9e6103SBrian Somers   else
1968dbb1e2bSBrian Somers     ios.c_cflag |= CLOCAL;
1975d9e6103SBrian Somers 
1985d9e6103SBrian Somers   if (p->type != PHYS_DEDICATED)
1998dbb1e2bSBrian Somers     ios.c_cflag |= HUPCL;
2005d9e6103SBrian Somers 
2018dbb1e2bSBrian Somers   tcsetattr(p->fd, TCSANOW, &ios);
2025d9e6103SBrian Somers 
2035d9e6103SBrian Somers   oldflag = fcntl(p->fd, F_GETFL, 0);
2045d9e6103SBrian Somers   if (oldflag < 0)
2055d9e6103SBrian Somers     return 0;
2065d9e6103SBrian Somers   fcntl(p->fd, F_SETFL, oldflag | O_NONBLOCK);
2075d9e6103SBrian Somers 
2086815097bSBrian Somers   if (ioctl(p->fd, TIOCMGET, &dev->mbits) == 0)
2095d9e6103SBrian Somers     tty_StartTimer(p);
2105d9e6103SBrian Somers 
2115d9e6103SBrian Somers   return 1;
2125d9e6103SBrian Somers }
2135d9e6103SBrian Somers 
2145d9e6103SBrian Somers static void
2155d9e6103SBrian Somers tty_Offline(struct physical *p)
2165d9e6103SBrian Somers {
2176815097bSBrian Somers   struct ttydevice *dev = device2tty(p->handler);
2186815097bSBrian Somers 
2195d9e6103SBrian Somers   if (p->fd >= 0) {
2206815097bSBrian Somers     timer_Stop(&dev->Timer);
2216815097bSBrian Somers     dev->mbits &= ~TIOCM_DTR;
2226815097bSBrian Somers     if (Online(dev)) {
2235d9e6103SBrian Somers       struct termios tio;
2245d9e6103SBrian Somers 
2255d9e6103SBrian Somers       tcgetattr(p->fd, &tio);
2265d9e6103SBrian Somers       if (cfsetspeed(&tio, B0) == -1)
2275d9e6103SBrian Somers         log_Printf(LogWARN, "%s: Unable to set physical to speed 0\n",
2285d9e6103SBrian Somers                    p->link.name);
2295d9e6103SBrian Somers       else
2305d9e6103SBrian Somers         tcsetattr(p->fd, TCSANOW, &tio);
2315d9e6103SBrian Somers     }
2325d9e6103SBrian Somers   }
2335d9e6103SBrian Somers }
2345d9e6103SBrian Somers 
2355d9e6103SBrian Somers static void
2365d9e6103SBrian Somers tty_Cooked(struct physical *p)
2375d9e6103SBrian Somers {
2386815097bSBrian Somers   struct ttydevice *dev = device2tty(p->handler);
2395d9e6103SBrian Somers   int oldflag;
2405d9e6103SBrian Somers 
241d0b3b745SBrian Somers   tty_Offline(p);	/* In case of emergency close()s */
242d0b3b745SBrian Somers 
2435d9e6103SBrian Somers   tcflush(p->fd, TCIOFLUSH);
2445d9e6103SBrian Somers   if (!physical_IsSync(p)) {
2456815097bSBrian Somers     tcsetattr(p->fd, TCSAFLUSH, &dev->ios);
2465d9e6103SBrian Somers     oldflag = fcntl(p->fd, F_GETFL, 0);
2475d9e6103SBrian Somers     if (oldflag == 0)
2485d9e6103SBrian Somers       fcntl(p->fd, F_SETFL, oldflag & ~O_NONBLOCK);
2495d9e6103SBrian Somers   }
2505d9e6103SBrian Somers }
2515d9e6103SBrian Somers 
2525d9e6103SBrian Somers static void
2536815097bSBrian Somers tty_StopTimer(struct physical *p)
2545d9e6103SBrian Somers {
2556815097bSBrian Somers   struct ttydevice *dev = device2tty(p->handler);
2566815097bSBrian Somers 
2576815097bSBrian Somers   timer_Stop(&dev->Timer);
2585d9e6103SBrian Somers }
2595d9e6103SBrian Somers 
2605d9e6103SBrian Somers static void
2616815097bSBrian Somers tty_Free(struct physical *p)
2625d9e6103SBrian Somers {
2636815097bSBrian Somers   struct ttydevice *dev = device2tty(p->handler);
2646815097bSBrian Somers 
265d0b3b745SBrian Somers   tty_Offline(p);	/* In case of emergency close()s */
2666815097bSBrian Somers   free(dev);
2675d9e6103SBrian Somers }
2685d9e6103SBrian Somers 
2695d9e6103SBrian Somers static int
2705d9e6103SBrian Somers tty_Speed(struct physical *p)
2715d9e6103SBrian Somers {
2728dbb1e2bSBrian Somers   struct termios ios;
2735d9e6103SBrian Somers 
2748dbb1e2bSBrian Somers   if (tcgetattr(p->fd, &ios) == -1)
2755d9e6103SBrian Somers     return 0;
2765d9e6103SBrian Somers 
2778dbb1e2bSBrian Somers   return SpeedToInt(cfgetispeed(&ios));
2785d9e6103SBrian Somers }
2795d9e6103SBrian Somers 
2805d9e6103SBrian Somers static const char *
2815d9e6103SBrian Somers tty_OpenInfo(struct physical *p)
2825d9e6103SBrian Somers {
2836815097bSBrian Somers   struct ttydevice *dev = device2tty(p->handler);
2845d9e6103SBrian Somers   static char buf[13];
2855d9e6103SBrian Somers 
2866815097bSBrian Somers   if (Online(dev))
2875d9e6103SBrian Somers     strcpy(buf, "with");
2885d9e6103SBrian Somers   else
2895d9e6103SBrian Somers     strcpy(buf, "no");
2905d9e6103SBrian Somers   strcat(buf, " carrier");
2915d9e6103SBrian Somers   return buf;
2925d9e6103SBrian Somers }
2935d9e6103SBrian Somers 
2946815097bSBrian Somers static void
2956815097bSBrian Somers tty_device2iov(struct physical *p, struct iovec *iov, int *niov,
2966815097bSBrian Somers                int maxiov, pid_t newpid)
2976815097bSBrian Somers {
2986815097bSBrian Somers   struct ttydevice *dev = p ? device2tty(p->handler) : NULL;
2996815097bSBrian Somers 
3006815097bSBrian Somers   iov[*niov].iov_base = p ? p->handler : malloc(sizeof(struct ttydevice));
3016815097bSBrian Somers   iov[*niov].iov_len = sizeof(struct ttydevice);
3026815097bSBrian Somers   (*niov)++;
3036815097bSBrian Somers 
3046815097bSBrian Somers   if (dev->Timer.state != TIMER_STOPPED) {
3056815097bSBrian Somers     timer_Stop(&dev->Timer);
3066815097bSBrian Somers     dev->Timer.state = TIMER_RUNNING;
3076815097bSBrian Somers   }
3086815097bSBrian Somers }
3096815097bSBrian Somers 
3106815097bSBrian Somers static struct device basettydevice = {
3115d9e6103SBrian Somers   TTY_DEVICE,
3125d9e6103SBrian Somers   "tty",
3135d9e6103SBrian Somers   tty_Raw,
3145d9e6103SBrian Somers   tty_Offline,
3155d9e6103SBrian Somers   tty_Cooked,
3166815097bSBrian Somers   tty_StopTimer,
3176815097bSBrian Somers   tty_Free,
3186815097bSBrian Somers   NULL,
3196815097bSBrian Somers   NULL,
3206815097bSBrian Somers   tty_device2iov,
3215d9e6103SBrian Somers   tty_Speed,
3225d9e6103SBrian Somers   tty_OpenInfo
3235d9e6103SBrian Somers };
3246815097bSBrian Somers 
3259950fb2aSBrian Somers struct device *
3269950fb2aSBrian Somers tty_iov2device(int type, struct physical *p, struct iovec *iov, int *niov,
3279950fb2aSBrian Somers                int maxiov)
3289950fb2aSBrian Somers {
3299950fb2aSBrian Somers   if (type == TTY_DEVICE) {
330acbd1f00SBrian Somers     struct ttydevice *dev = (struct ttydevice *)iov[(*niov)++].iov_base;
3319950fb2aSBrian Somers 
3329950fb2aSBrian Somers     /* Refresh function pointers etc */
3339950fb2aSBrian Somers     memcpy(&dev->dev, &basettydevice, sizeof dev->dev);
3349950fb2aSBrian Somers 
335acbd1f00SBrian Somers     physical_SetupStack(p, dev->dev.name, PHYSICAL_NOFORCE);
3369950fb2aSBrian Somers     if (dev->Timer.state != TIMER_STOPPED) {
3379950fb2aSBrian Somers       dev->Timer.state = TIMER_STOPPED;
3389950fb2aSBrian Somers       tty_StartTimer(p);
3399950fb2aSBrian Somers     }
3409950fb2aSBrian Somers     return &dev->dev;
3419950fb2aSBrian Somers   }
3429950fb2aSBrian Somers 
3439950fb2aSBrian Somers   return NULL;
3449950fb2aSBrian Somers }
3459950fb2aSBrian Somers 
3469950fb2aSBrian Somers struct device *
3479950fb2aSBrian Somers tty_Create(struct physical *p)
34827be3ac6SBrian Somers {
34927be3ac6SBrian Somers   struct ttydevice *dev;
35027be3ac6SBrian Somers   struct termios ios;
35127be3ac6SBrian Somers   int oldflag;
35227be3ac6SBrian Somers 
3539950fb2aSBrian Somers   if (p->fd < 0 || !isatty(p->fd))
3549950fb2aSBrian Somers     /* Don't want this */
35527be3ac6SBrian Somers     return NULL;
35627be3ac6SBrian Somers 
3579950fb2aSBrian Somers   if (*p->name.full == '\0') {
3589950fb2aSBrian Somers     physical_SetDevice(p, ttyname(p->fd));
3599950fb2aSBrian Somers     log_Printf(LogDEBUG, "%s: Input is a tty (%s)\n",
3609950fb2aSBrian Somers                p->link.name, p->name.full);
3619950fb2aSBrian Somers   } else
3629950fb2aSBrian Somers     log_Printf(LogDEBUG, "%s: Opened %s\n", p->link.name, p->name.full);
3639950fb2aSBrian Somers 
3649950fb2aSBrian Somers   /* We're gonna return a ttydevice (unless something goes horribly wrong) */
3659950fb2aSBrian Somers 
3669950fb2aSBrian Somers   if ((dev = malloc(sizeof *dev)) == NULL) {
3679950fb2aSBrian Somers     /* Complete failure - parent doesn't continue trying to ``create'' */
3689950fb2aSBrian Somers     close(p->fd);
3699950fb2aSBrian Somers     p->fd = -1;
3709950fb2aSBrian Somers     return NULL;
3719950fb2aSBrian Somers   }
3729950fb2aSBrian Somers 
37327be3ac6SBrian Somers   memcpy(&dev->dev, &basettydevice, sizeof dev->dev);
3744b698945SBrian Somers   memset(&dev->Timer, '\0', sizeof dev->Timer);
37527be3ac6SBrian Somers   tcgetattr(p->fd, &ios);
37627be3ac6SBrian Somers   dev->ios = ios;
37727be3ac6SBrian Somers 
3789950fb2aSBrian Somers   log_Printf(LogDEBUG, "%s: tty_Create: physical (get): fd = %d,"
37927be3ac6SBrian Somers              " iflag = %lx, oflag = %lx, cflag = %lx\n", p->link.name, p->fd,
38027be3ac6SBrian Somers              (u_long)ios.c_iflag, (u_long)ios.c_oflag, (u_long)ios.c_cflag);
38127be3ac6SBrian Somers 
38227be3ac6SBrian Somers   cfmakeraw(&ios);
38327be3ac6SBrian Somers   if (p->cfg.rts_cts)
38427be3ac6SBrian Somers     ios.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW;
38527be3ac6SBrian Somers   else {
38627be3ac6SBrian Somers     ios.c_cflag |= CLOCAL;
38727be3ac6SBrian Somers     ios.c_iflag |= IXOFF;
38827be3ac6SBrian Somers   }
38927be3ac6SBrian Somers   ios.c_iflag |= IXON;
39027be3ac6SBrian Somers   if (p->type != PHYS_DEDICATED)
39127be3ac6SBrian Somers     ios.c_cflag |= HUPCL;
39227be3ac6SBrian Somers 
39327be3ac6SBrian Somers   if (p->type != PHYS_DIRECT) {
39427be3ac6SBrian Somers       /* Change tty speed when we're not in -direct mode */
39527be3ac6SBrian Somers       ios.c_cflag &= ~(CSIZE | PARODD | PARENB);
39627be3ac6SBrian Somers       ios.c_cflag |= p->cfg.parity;
39727be3ac6SBrian Somers       if (cfsetspeed(&ios, IntToSpeed(p->cfg.speed)) == -1)
39827be3ac6SBrian Somers 	log_Printf(LogWARN, "%s: %s: Unable to set speed to %d\n",
39927be3ac6SBrian Somers 		  p->link.name, p->name.full, p->cfg.speed);
40027be3ac6SBrian Somers   }
40127be3ac6SBrian Somers   tcsetattr(p->fd, TCSADRAIN, &ios);
40227be3ac6SBrian Somers   log_Printf(LogDEBUG, "%s: physical (put): iflag = %lx, oflag = %lx, "
40327be3ac6SBrian Somers             "cflag = %lx\n", p->link.name, (u_long)ios.c_iflag,
40427be3ac6SBrian Somers             (u_long)ios.c_oflag, (u_long)ios.c_cflag);
40527be3ac6SBrian Somers 
40627be3ac6SBrian Somers   if (ioctl(p->fd, TIOCMGET, &dev->mbits) == -1) {
40727be3ac6SBrian Somers     if (p->type != PHYS_DIRECT) {
4089950fb2aSBrian Somers       /* Complete failure - parent doesn't continue trying to ``create'' */
4099950fb2aSBrian Somers 
41027be3ac6SBrian Somers       log_Printf(LogWARN, "%s: Open: Cannot get physical status: %s\n",
41127be3ac6SBrian Somers                  p->link.name, strerror(errno));
4129950fb2aSBrian Somers       tty_Cooked(p);
4139950fb2aSBrian Somers       close(p->fd);
4149950fb2aSBrian Somers       p->fd = -1;
41527be3ac6SBrian Somers       return NULL;
41627be3ac6SBrian Somers     } else
41727be3ac6SBrian Somers       dev->mbits = TIOCM_CD;
41827be3ac6SBrian Somers   }
41927be3ac6SBrian Somers   log_Printf(LogDEBUG, "%s: Open: physical control = %o\n",
42027be3ac6SBrian Somers              p->link.name, dev->mbits);
42127be3ac6SBrian Somers 
42227be3ac6SBrian Somers   oldflag = fcntl(p->fd, F_GETFL, 0);
42327be3ac6SBrian Somers   if (oldflag < 0) {
4249950fb2aSBrian Somers     /* Complete failure - parent doesn't continue trying to ``create'' */
4259950fb2aSBrian Somers 
42627be3ac6SBrian Somers     log_Printf(LogWARN, "%s: Open: Cannot get physical flags: %s\n",
42727be3ac6SBrian Somers                p->link.name, strerror(errno));
4289950fb2aSBrian Somers     tty_Cooked(p);
4299950fb2aSBrian Somers     close(p->fd);
4309950fb2aSBrian Somers     p->fd = -1;
43127be3ac6SBrian Somers     return NULL;
43227be3ac6SBrian Somers   } else
43327be3ac6SBrian Somers     fcntl(p->fd, F_SETFL, oldflag & ~O_NONBLOCK);
43427be3ac6SBrian Somers 
435acbd1f00SBrian Somers   physical_SetupStack(p, dev->dev.name, PHYSICAL_NOFORCE);
43627be3ac6SBrian Somers 
43727be3ac6SBrian Somers   return &dev->dev;
43827be3ac6SBrian Somers }
439