xref: /freebsd/usr.sbin/ppp/prompt.c (revision 1b35f8f70349c56eaae8c72a3de1e59db56da9c0)
185b542cfSBrian Somers /*-
285b542cfSBrian Somers  * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
385b542cfSBrian Somers  * All rights reserved.
485b542cfSBrian Somers  *
585b542cfSBrian Somers  * Redistribution and use in source and binary forms, with or without
685b542cfSBrian Somers  * modification, are permitted provided that the following conditions
785b542cfSBrian Somers  * are met:
885b542cfSBrian Somers  * 1. Redistributions of source code must retain the above copyright
985b542cfSBrian Somers  *    notice, this list of conditions and the following disclaimer.
1085b542cfSBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
1185b542cfSBrian Somers  *    notice, this list of conditions and the following disclaimer in the
1285b542cfSBrian Somers  *    documentation and/or other materials provided with the distribution.
1385b542cfSBrian Somers  *
1485b542cfSBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1585b542cfSBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1685b542cfSBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1785b542cfSBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1885b542cfSBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1985b542cfSBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2085b542cfSBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2185b542cfSBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2285b542cfSBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2385b542cfSBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2485b542cfSBrian Somers  * SUCH DAMAGE.
2585b542cfSBrian Somers  *
261b35f8f7SBrian Somers  *	$Id: prompt.c,v 1.1.2.5 1998/02/17 19:28:00 brian Exp $
2785b542cfSBrian Somers  */
2885b542cfSBrian Somers 
2985b542cfSBrian Somers #include <sys/param.h>
3085b542cfSBrian Somers #include <netinet/in.h>
3185b542cfSBrian Somers 
3285b542cfSBrian Somers #include <stdarg.h>
3385b542cfSBrian Somers #include <stdio.h>
3485b542cfSBrian Somers #include <sys/fcntl.h>
3585b542cfSBrian Somers #include <sys/stat.h>
3685b542cfSBrian Somers #include <termios.h>
3785b542cfSBrian Somers #include <unistd.h>
3885b542cfSBrian Somers 
3985b542cfSBrian Somers #include "defs.h"
4085b542cfSBrian Somers #include "timer.h"
4185b542cfSBrian Somers #include "command.h"
4285b542cfSBrian Somers #include "log.h"
4385b542cfSBrian Somers #include "bundle.h"
4485b542cfSBrian Somers #include "descriptor.h"
4585b542cfSBrian Somers #include "prompt.h"
4685b542cfSBrian Somers #include "fsm.h"
4785b542cfSBrian Somers #include "lcp.h"
4885b542cfSBrian Somers #include "auth.h"
4985b542cfSBrian Somers #include "loadalias.h"
5085b542cfSBrian Somers #include "vars.h"
5185b542cfSBrian Somers #include "main.h"
5285b542cfSBrian Somers #include "iplist.h"
5385b542cfSBrian Somers #include "throughput.h"
5485b542cfSBrian Somers #include "ipcp.h"
553006ec67SBrian Somers #include "hdlc.h"
563006ec67SBrian Somers #include "async.h"
573006ec67SBrian Somers #include "mbuf.h"
583006ec67SBrian Somers #include "link.h"
593006ec67SBrian Somers #include "physical.h"
60c5a5a6caSBrian Somers #include "chat.h"
61c5a5a6caSBrian Somers #include "datalink.h"
6285b542cfSBrian Somers 
6385b542cfSBrian Somers static int prompt_nonewline = 1;
6485b542cfSBrian Somers 
6585b542cfSBrian Somers static int
6685b542cfSBrian Somers prompt_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
6785b542cfSBrian Somers {
6885b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
69b6dec9f0SBrian Somers   int sets;
7085b542cfSBrian Somers 
7185b542cfSBrian Somers   LogPrintf(LogDEBUG, "descriptor2prompt; %p -> %p\n", d, p);
7285b542cfSBrian Somers 
73b6dec9f0SBrian Somers   sets = 0;
7485b542cfSBrian Somers   if (p->fd_in >= 0) {
75b6dec9f0SBrian Somers     if (r) {
7685b542cfSBrian Somers       FD_SET(p->fd_in, r);
77b6dec9f0SBrian Somers       sets++;
78b6dec9f0SBrian Somers     }
79b6dec9f0SBrian Somers     if (e) {
8085b542cfSBrian Somers       FD_SET(p->fd_in, e);
81b6dec9f0SBrian Somers       sets++;
82b6dec9f0SBrian Somers     }
83b6dec9f0SBrian Somers     if (sets && *n < p->fd_in + 1)
84b6dec9f0SBrian Somers       *n = p->fd_in + 1;
8585b542cfSBrian Somers   }
8685b542cfSBrian Somers 
87b6dec9f0SBrian Somers   return sets;
8885b542cfSBrian Somers }
8985b542cfSBrian Somers 
9085b542cfSBrian Somers static int
9185b542cfSBrian Somers prompt_IsSet(struct descriptor *d, fd_set *fdset)
9285b542cfSBrian Somers {
9385b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
9485b542cfSBrian Somers   LogPrintf(LogDEBUG, "descriptor2prompt; %p -> %p\n", d, p);
9585b542cfSBrian Somers   return p->fd_in >= 0 && FD_ISSET(p->fd_in, fdset);
9685b542cfSBrian Somers }
9785b542cfSBrian Somers 
9885b542cfSBrian Somers 
9985b542cfSBrian Somers static void
10085b542cfSBrian Somers prompt_ShowHelp(struct prompt *p)
10185b542cfSBrian Somers {
10285b542cfSBrian Somers   prompt_Printf(p, "The following commands are available:\r\n");
10385b542cfSBrian Somers   prompt_Printf(p, " ~p\tEnter Packet mode\r\n");
10485b542cfSBrian Somers   prompt_Printf(p, " ~-\tDecrease log level\r\n");
10585b542cfSBrian Somers   prompt_Printf(p, " ~+\tIncrease log level\r\n");
10685b542cfSBrian Somers   prompt_Printf(p, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
10785b542cfSBrian Somers   prompt_Printf(p, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
10885b542cfSBrian Somers   prompt_Printf(p, " ~.\tTerminate program\r\n");
10985b542cfSBrian Somers   prompt_Printf(p, " ~?\tThis help\r\n");
11085b542cfSBrian Somers }
11185b542cfSBrian Somers 
11285b542cfSBrian Somers static void
11385b542cfSBrian Somers prompt_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
11485b542cfSBrian Somers {
11585b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
11685b542cfSBrian Somers   int n;
11785b542cfSBrian Somers   char ch;
11885b542cfSBrian Somers   static int ttystate;
11985b542cfSBrian Somers   char linebuff[LINE_LEN];
12085b542cfSBrian Somers 
1211b35f8f7SBrian Somers   if (p->TermMode != NULL) {
1221b35f8f7SBrian Somers     if (p->TermMode->state == DATALINK_CLOSED) {
123c5a5a6caSBrian Somers       prompt_Printf(p, "Exiting terminal mode.\n");
124c5a5a6caSBrian Somers       prompt_TtyCommandMode(&prompt);
125c5a5a6caSBrian Somers       prompt_nonewline = 0;
126c5a5a6caSBrian Somers       prompt_Display(&prompt, bundle);
127c5a5a6caSBrian Somers     }
128aef795ccSBrian Somers 
1291b35f8f7SBrian Somers     if (p->TermMode->state != DATALINK_OPEN)
130c5a5a6caSBrian Somers       return;
131c5a5a6caSBrian Somers   }
132c5a5a6caSBrian Somers 
13385b542cfSBrian Somers   LogPrintf(LogDEBUG, "descriptor2prompt; %p -> %p\n", d, p);
1341b35f8f7SBrian Somers   LogPrintf(LogDEBUG, "termode = %p, p->fd_in = %d, mode = %d\n",
13585b542cfSBrian Somers 	    p->TermMode, p->fd_in, mode);
13685b542cfSBrian Somers 
1371b35f8f7SBrian Somers   if (p->TermMode == NULL) {
13885b542cfSBrian Somers     n = read(p->fd_in, linebuff, sizeof linebuff - 1);
13985b542cfSBrian Somers     if (n > 0) {
14085b542cfSBrian Somers       if (linebuff[n-1] == '\n')
14185b542cfSBrian Somers         linebuff[--n] = '\0';
14285b542cfSBrian Somers       else
14385b542cfSBrian Somers         linebuff[n] = '\0';
14485b542cfSBrian Somers       if (n)
14585b542cfSBrian Somers         DecodeCommand(bundle, linebuff, n, IsInteractive(0) ? NULL : "Client");
14685b542cfSBrian Somers       prompt_nonewline = 1;
14785b542cfSBrian Somers       prompt_Display(&prompt, bundle);
14885b542cfSBrian Somers     } else if (n <= 0) {
14985b542cfSBrian Somers       LogPrintf(LogPHASE, "Client connection closed.\n");
15085b542cfSBrian Somers       prompt_Drop(&prompt, 0);
15185b542cfSBrian Somers     }
15285b542cfSBrian Somers     return;
15385b542cfSBrian Somers   }
15485b542cfSBrian Somers 
15585b542cfSBrian Somers   /*
15685b542cfSBrian Somers    * We are in terminal mode, decode special sequences
15785b542cfSBrian Somers    */
15885b542cfSBrian Somers   n = read(p->fd_in, &ch, 1);
15985b542cfSBrian Somers   LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
16085b542cfSBrian Somers 
16185b542cfSBrian Somers   if (n > 0) {
16285b542cfSBrian Somers     switch (ttystate) {
16385b542cfSBrian Somers     case 0:
16485b542cfSBrian Somers       if (ch == '~')
16585b542cfSBrian Somers 	ttystate++;
16685b542cfSBrian Somers       else
16785b542cfSBrian Somers 	/* XXX missing return value check */
1683006ec67SBrian Somers 	Physical_Write(bundle2physical(bundle, NULL), &ch, n);
16985b542cfSBrian Somers       break;
17085b542cfSBrian Somers     case 1:
17185b542cfSBrian Somers       switch (ch) {
17285b542cfSBrian Somers       case '?':
17385b542cfSBrian Somers 	prompt_ShowHelp(p);
17485b542cfSBrian Somers 	break;
17585b542cfSBrian Somers       case 'p':
17685b542cfSBrian Somers 
17785b542cfSBrian Somers 	/*
17885b542cfSBrian Somers 	 * XXX: Should check carrier.
17985b542cfSBrian Somers 	 */
18085b542cfSBrian Somers 	if (LcpInfo.fsm.state <= ST_CLOSED)
18185b542cfSBrian Somers 	  PacketMode(bundle, 0);
18285b542cfSBrian Somers 	break;
18385b542cfSBrian Somers       case '.':
18485b542cfSBrian Somers 	prompt_TtyCommandMode(&prompt);
18585b542cfSBrian Somers         prompt_nonewline = 0;
18685b542cfSBrian Somers         prompt_Display(&prompt, bundle);
18785b542cfSBrian Somers 	break;
18885b542cfSBrian Somers       case 't':
18985b542cfSBrian Somers 	if (LogIsKept(LogDEBUG)) {
19085b542cfSBrian Somers 	  ShowTimers();
19185b542cfSBrian Somers 	  break;
19285b542cfSBrian Somers 	}
19385b542cfSBrian Somers       case 'm':
19485b542cfSBrian Somers 	if (LogIsKept(LogDEBUG)) {
19585b542cfSBrian Somers 	  ShowMemMap(NULL);
19685b542cfSBrian Somers 	  break;
19785b542cfSBrian Somers 	}
19885b542cfSBrian Somers       default:
1993006ec67SBrian Somers 	if (Physical_Write(bundle2physical(bundle, NULL), &ch, n) < 0)
20085b542cfSBrian Somers 	  LogPrintf(LogERROR, "error writing to modem.\n");
20185b542cfSBrian Somers 	break;
20285b542cfSBrian Somers       }
20385b542cfSBrian Somers       ttystate = 0;
20485b542cfSBrian Somers       break;
20585b542cfSBrian Somers     }
20685b542cfSBrian Somers   }
20785b542cfSBrian Somers }
20885b542cfSBrian Somers 
20985b542cfSBrian Somers static void
21085b542cfSBrian Somers prompt_Write(struct descriptor *d, const fd_set *fdset)
21185b542cfSBrian Somers {
21285b542cfSBrian Somers   /* We don't set the write descriptor (yet) */
21385b542cfSBrian Somers }
21485b542cfSBrian Somers 
21585b542cfSBrian Somers struct prompt prompt = {
21685b542cfSBrian Somers   {
21785b542cfSBrian Somers     PROMPT_DESCRIPTOR,
21885b542cfSBrian Somers     NULL,
21985b542cfSBrian Somers     prompt_UpdateSet,
22085b542cfSBrian Somers     prompt_IsSet,
22185b542cfSBrian Somers     prompt_Read,
22285b542cfSBrian Somers     prompt_Write
22385b542cfSBrian Somers   },
22485b542cfSBrian Somers   -1,
22585b542cfSBrian Somers   -1,
22685b542cfSBrian Somers   NULL
22785b542cfSBrian Somers };
22885b542cfSBrian Somers 
22985b542cfSBrian Somers int
23085b542cfSBrian Somers prompt_Init(struct prompt *p, int fd)
23185b542cfSBrian Somers {
23285b542cfSBrian Somers   if (p->Term && p->Term != stdout)
23385b542cfSBrian Somers     return 0;                       /* must prompt_Drop() first */
23485b542cfSBrian Somers 
23585b542cfSBrian Somers   if (fd == PROMPT_NONE) {
23685b542cfSBrian Somers     p->fd_in = p->fd_out = -1;
23785b542cfSBrian Somers     p->Term = NULL;
23885b542cfSBrian Somers   } else if (fd == PROMPT_STD) {
23985b542cfSBrian Somers     p->fd_in = STDIN_FILENO;
24085b542cfSBrian Somers     p->fd_out = STDOUT_FILENO;
24185b542cfSBrian Somers     p->Term = stdout;
24285b542cfSBrian Somers   } else {
24385b542cfSBrian Somers     p->fd_in = p->fd_out = fd;
24485b542cfSBrian Somers     p->Term = fdopen(fd, "a+");
24585b542cfSBrian Somers   }
2461b35f8f7SBrian Somers   p->TermMode = NULL;
24785b542cfSBrian Somers   tcgetattr(STDIN_FILENO, &p->oldtio);	/* Save original tty mode */
24885b542cfSBrian Somers 
24985b542cfSBrian Somers   return 1;
25085b542cfSBrian Somers }
25185b542cfSBrian Somers 
2523006ec67SBrian Somers void
25385b542cfSBrian Somers prompt_Display(struct prompt *p, struct bundle *bundle)
25485b542cfSBrian Somers {
25585b542cfSBrian Somers   const char *pconnect, *pauth;
25685b542cfSBrian Somers 
2571b35f8f7SBrian Somers   if (!p->Term || p->TermMode != NULL || CleaningUp)
25885b542cfSBrian Somers     return;
25985b542cfSBrian Somers 
26085b542cfSBrian Somers   if (prompt_nonewline)
26185b542cfSBrian Somers     prompt_nonewline = 0;
26285b542cfSBrian Somers   else
26385b542cfSBrian Somers     fprintf(p->Term, "\n");
26485b542cfSBrian Somers 
26585b542cfSBrian Somers   if (VarLocalAuth == LOCAL_AUTH)
26685b542cfSBrian Somers     pauth = " ON ";
26785b542cfSBrian Somers   else
26885b542cfSBrian Somers     pauth = " on ";
26985b542cfSBrian Somers 
27085b542cfSBrian Somers   if (IpcpInfo.fsm.state == ST_OPENED)
27185b542cfSBrian Somers     pconnect = "PPP";
27285b542cfSBrian Somers   else if (bundle_Phase(bundle) == PHASE_NETWORK)
27385b542cfSBrian Somers     pconnect = "PPp";
27485b542cfSBrian Somers   else if (bundle_Phase(bundle) == PHASE_AUTHENTICATE)
27585b542cfSBrian Somers     pconnect = "Ppp";
27685b542cfSBrian Somers   else
27785b542cfSBrian Somers     pconnect = "ppp";
27885b542cfSBrian Somers 
27985b542cfSBrian Somers   fprintf(p->Term, "%s%s%s> ", pconnect, pauth, VarShortHost);
28085b542cfSBrian Somers   fflush(p->Term);
28185b542cfSBrian Somers }
28285b542cfSBrian Somers 
28385b542cfSBrian Somers void
28485b542cfSBrian Somers prompt_Drop(struct prompt *p, int verbose)
28585b542cfSBrian Somers {
28685b542cfSBrian Somers   if (p->Term && p->Term != stdout) {
28785b542cfSBrian Somers     FILE *oVarTerm;
28885b542cfSBrian Somers 
28985b542cfSBrian Somers     oVarTerm = p->Term;
29085b542cfSBrian Somers     p->Term = NULL;
29185b542cfSBrian Somers     if (oVarTerm)
29285b542cfSBrian Somers       fclose(oVarTerm);
29385b542cfSBrian Somers     close(p->fd_in);
29485b542cfSBrian Somers     if (p->fd_out != p->fd_in)
29585b542cfSBrian Somers       close(p->fd_out);
29685b542cfSBrian Somers     p->fd_in = p->fd_out = -1;
29785b542cfSBrian Somers     if (verbose)
29885b542cfSBrian Somers       LogPrintf(LogPHASE, "Client connection dropped.\n");
29985b542cfSBrian Somers   }
30085b542cfSBrian Somers }
30185b542cfSBrian Somers 
30285b542cfSBrian Somers void
30385b542cfSBrian Somers prompt_Printf(struct prompt *p, const char *fmt,...)
30485b542cfSBrian Somers {
30585b542cfSBrian Somers   if (p->Term) {
30685b542cfSBrian Somers     va_list ap;
30785b542cfSBrian Somers 
30885b542cfSBrian Somers     va_start(ap, fmt);
30985b542cfSBrian Somers     vfprintf(p->Term, fmt, ap);
31085b542cfSBrian Somers     fflush(p->Term);
31185b542cfSBrian Somers     va_end(ap);
31285b542cfSBrian Somers   }
31385b542cfSBrian Somers }
31485b542cfSBrian Somers 
31585b542cfSBrian Somers void
31685b542cfSBrian Somers prompt_vPrintf(struct prompt *p, const char *fmt, va_list ap)
31785b542cfSBrian Somers {
31885b542cfSBrian Somers   if (p->Term) {
31985b542cfSBrian Somers     vfprintf(p->Term, fmt, ap);
32085b542cfSBrian Somers     fflush(p->Term);
32185b542cfSBrian Somers   }
32285b542cfSBrian Somers }
32385b542cfSBrian Somers 
32485b542cfSBrian Somers void
32585b542cfSBrian Somers prompt_TtyInit(struct prompt *p, int DontWantInt)
32685b542cfSBrian Somers {
32785b542cfSBrian Somers   struct termios newtio;
32885b542cfSBrian Somers   int stat;
32985b542cfSBrian Somers 
33085b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
33185b542cfSBrian Somers   if (stat > 0) {
33285b542cfSBrian Somers     stat |= O_NONBLOCK;
33385b542cfSBrian Somers     (void) fcntl(p->fd_in, F_SETFL, stat);
33485b542cfSBrian Somers   }
33585b542cfSBrian Somers   newtio = p->oldtio;
33685b542cfSBrian Somers   newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
33785b542cfSBrian Somers   newtio.c_iflag = 0;
33885b542cfSBrian Somers   newtio.c_oflag &= ~OPOST;
33985b542cfSBrian Somers   newtio.c_cc[VEOF] = _POSIX_VDISABLE;
34085b542cfSBrian Somers   if (DontWantInt)
34185b542cfSBrian Somers     newtio.c_cc[VINTR] = _POSIX_VDISABLE;
34285b542cfSBrian Somers   newtio.c_cc[VMIN] = 1;
34385b542cfSBrian Somers   newtio.c_cc[VTIME] = 0;
34485b542cfSBrian Somers   newtio.c_cflag |= CS8;
34585b542cfSBrian Somers   tcsetattr(p->fd_in, TCSANOW, &newtio);
34685b542cfSBrian Somers   p->comtio = newtio;
34785b542cfSBrian Somers }
34885b542cfSBrian Somers 
34985b542cfSBrian Somers /*
35085b542cfSBrian Somers  *  Set tty into command mode. We allow canonical input and echo processing.
35185b542cfSBrian Somers  */
35285b542cfSBrian Somers void
35385b542cfSBrian Somers prompt_TtyCommandMode(struct prompt *p)
35485b542cfSBrian Somers {
35585b542cfSBrian Somers   struct termios newtio;
35685b542cfSBrian Somers   int stat;
35785b542cfSBrian Somers 
35885b542cfSBrian Somers   if (!(mode & MODE_INTER))
35985b542cfSBrian Somers     return;
36085b542cfSBrian Somers 
36185b542cfSBrian Somers   tcgetattr(p->fd_in, &newtio);
36285b542cfSBrian Somers   newtio.c_lflag |= (ECHO | ISIG | ICANON);
36385b542cfSBrian Somers   newtio.c_iflag = p->oldtio.c_iflag;
36485b542cfSBrian Somers   newtio.c_oflag |= OPOST;
36585b542cfSBrian Somers   tcsetattr(p->fd_in, TCSADRAIN, &newtio);
36685b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
36785b542cfSBrian Somers   if (stat > 0) {
36885b542cfSBrian Somers     stat |= O_NONBLOCK;
36985b542cfSBrian Somers     (void) fcntl(p->fd_in, F_SETFL, stat);
37085b542cfSBrian Somers   }
3711b35f8f7SBrian Somers   p->TermMode = NULL;
37285b542cfSBrian Somers }
37385b542cfSBrian Somers 
37485b542cfSBrian Somers /*
37585b542cfSBrian Somers  * Set tty into terminal mode which is used while we invoke term command.
37685b542cfSBrian Somers  */
37785b542cfSBrian Somers void
3781b35f8f7SBrian Somers prompt_TtyTermMode(struct prompt *p, struct datalink *dl)
37985b542cfSBrian Somers {
38085b542cfSBrian Somers   int stat;
38185b542cfSBrian Somers 
38285b542cfSBrian Somers   tcsetattr(p->fd_in, TCSADRAIN, &p->comtio);
38385b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
38485b542cfSBrian Somers   if (stat > 0) {
38585b542cfSBrian Somers     stat &= ~O_NONBLOCK;
38685b542cfSBrian Somers     (void) fcntl(p->fd_in, F_SETFL, stat);
38785b542cfSBrian Somers   }
3881b35f8f7SBrian Somers   p->TermMode = dl;
38985b542cfSBrian Somers }
39085b542cfSBrian Somers 
39185b542cfSBrian Somers void
39285b542cfSBrian Somers prompt_TtyOldMode(struct prompt *p)
39385b542cfSBrian Somers {
39485b542cfSBrian Somers   int stat;
39585b542cfSBrian Somers 
39685b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
39785b542cfSBrian Somers   if (stat > 0) {
39885b542cfSBrian Somers     stat &= ~O_NONBLOCK;
39985b542cfSBrian Somers     (void) fcntl(p->fd_in, F_SETFL, stat);
40085b542cfSBrian Somers   }
40185b542cfSBrian Somers   tcsetattr(p->fd_in, TCSADRAIN, &p->oldtio);
40285b542cfSBrian Somers }
40385b542cfSBrian Somers 
40485b542cfSBrian Somers pid_t
40585b542cfSBrian Somers prompt_pgrp(struct prompt *p)
40685b542cfSBrian Somers {
40785b542cfSBrian Somers   return p->Term ? tcgetpgrp(p->fd_in) : -1;
40885b542cfSBrian Somers }
409