xref: /freebsd/usr.sbin/ppp/prompt.c (revision f4768038f0d8815ef8b67f823150ddd10a48c165)
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  *
26f4768038SBrian Somers  *	$Id: prompt.c,v 1.1.2.7 1998/02/17 19:28:35 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"
61f4768038SBrian Somers #include "ccp.h"
62c5a5a6caSBrian Somers #include "datalink.h"
6385b542cfSBrian Somers 
6485b542cfSBrian Somers static int prompt_nonewline = 1;
6585b542cfSBrian Somers 
6685b542cfSBrian Somers static int
6785b542cfSBrian Somers prompt_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
6885b542cfSBrian Somers {
6985b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
70b6dec9f0SBrian Somers   int sets;
7185b542cfSBrian Somers 
7285b542cfSBrian Somers   LogPrintf(LogDEBUG, "descriptor2prompt; %p -> %p\n", d, p);
7385b542cfSBrian Somers 
74b6dec9f0SBrian Somers   sets = 0;
7585b542cfSBrian Somers   if (p->fd_in >= 0) {
76b6dec9f0SBrian Somers     if (r) {
7785b542cfSBrian Somers       FD_SET(p->fd_in, r);
78b6dec9f0SBrian Somers       sets++;
79b6dec9f0SBrian Somers     }
80b6dec9f0SBrian Somers     if (e) {
8185b542cfSBrian Somers       FD_SET(p->fd_in, e);
82b6dec9f0SBrian Somers       sets++;
83b6dec9f0SBrian Somers     }
84b6dec9f0SBrian Somers     if (sets && *n < p->fd_in + 1)
85b6dec9f0SBrian Somers       *n = p->fd_in + 1;
8685b542cfSBrian Somers   }
8785b542cfSBrian Somers 
88b6dec9f0SBrian Somers   return sets;
8985b542cfSBrian Somers }
9085b542cfSBrian Somers 
9185b542cfSBrian Somers static int
9285b542cfSBrian Somers prompt_IsSet(struct descriptor *d, fd_set *fdset)
9385b542cfSBrian Somers {
9485b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
9585b542cfSBrian Somers   LogPrintf(LogDEBUG, "descriptor2prompt; %p -> %p\n", d, p);
9685b542cfSBrian Somers   return p->fd_in >= 0 && FD_ISSET(p->fd_in, fdset);
9785b542cfSBrian Somers }
9885b542cfSBrian Somers 
9985b542cfSBrian Somers 
10085b542cfSBrian Somers static void
10185b542cfSBrian Somers prompt_ShowHelp(struct prompt *p)
10285b542cfSBrian Somers {
10385b542cfSBrian Somers   prompt_Printf(p, "The following commands are available:\r\n");
10485b542cfSBrian Somers   prompt_Printf(p, " ~p\tEnter Packet mode\r\n");
10585b542cfSBrian Somers   prompt_Printf(p, " ~-\tDecrease log level\r\n");
10685b542cfSBrian Somers   prompt_Printf(p, " ~+\tIncrease log level\r\n");
10785b542cfSBrian Somers   prompt_Printf(p, " ~t\tShow timers (only in \"log debug\" mode)\r\n");
10885b542cfSBrian Somers   prompt_Printf(p, " ~m\tShow memory map (only in \"log debug\" mode)\r\n");
10985b542cfSBrian Somers   prompt_Printf(p, " ~.\tTerminate program\r\n");
11085b542cfSBrian Somers   prompt_Printf(p, " ~?\tThis help\r\n");
11185b542cfSBrian Somers }
11285b542cfSBrian Somers 
11385b542cfSBrian Somers static void
11485b542cfSBrian Somers prompt_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
11585b542cfSBrian Somers {
11685b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
11785b542cfSBrian Somers   int n;
11885b542cfSBrian Somers   char ch;
11985b542cfSBrian Somers   static int ttystate;
12085b542cfSBrian Somers   char linebuff[LINE_LEN];
12185b542cfSBrian Somers 
12285b542cfSBrian Somers   LogPrintf(LogDEBUG, "descriptor2prompt; %p -> %p\n", d, p);
1231b35f8f7SBrian Somers   LogPrintf(LogDEBUG, "termode = %p, p->fd_in = %d, mode = %d\n",
12485b542cfSBrian Somers 	    p->TermMode, p->fd_in, mode);
12585b542cfSBrian Somers 
1261b35f8f7SBrian Somers   if (p->TermMode == NULL) {
12785b542cfSBrian Somers     n = read(p->fd_in, linebuff, sizeof linebuff - 1);
12885b542cfSBrian Somers     if (n > 0) {
12985b542cfSBrian Somers       if (linebuff[n-1] == '\n')
13085b542cfSBrian Somers         linebuff[--n] = '\0';
13185b542cfSBrian Somers       else
13285b542cfSBrian Somers         linebuff[n] = '\0';
13385b542cfSBrian Somers       if (n)
13485b542cfSBrian Somers         DecodeCommand(bundle, linebuff, n, IsInteractive(0) ? NULL : "Client");
13585b542cfSBrian Somers       prompt_nonewline = 1;
13685b542cfSBrian Somers       prompt_Display(&prompt, bundle);
13785b542cfSBrian Somers     } else if (n <= 0) {
13885b542cfSBrian Somers       LogPrintf(LogPHASE, "Client connection closed.\n");
13985b542cfSBrian Somers       prompt_Drop(&prompt, 0);
14085b542cfSBrian Somers     }
14185b542cfSBrian Somers     return;
14285b542cfSBrian Somers   }
14385b542cfSBrian Somers 
144c7cc5030SBrian Somers   switch (p->TermMode->state) {
145c7cc5030SBrian Somers     case DATALINK_CLOSED:
146c7cc5030SBrian Somers       prompt_Printf(p, "Link lost, terminal mode.\n");
147c7cc5030SBrian Somers       prompt_TtyCommandMode(&prompt);
148c7cc5030SBrian Somers       prompt_nonewline = 0;
149c7cc5030SBrian Somers       prompt_Display(&prompt, bundle);
150c7cc5030SBrian Somers       return;
151c7cc5030SBrian Somers 
152c7cc5030SBrian Somers     case DATALINK_READY:
153c7cc5030SBrian Somers       break;
154c7cc5030SBrian Somers 
155c7cc5030SBrian Somers     case DATALINK_OPEN:
156c7cc5030SBrian Somers       prompt_Printf(p, "\nPacket mode detected.\n");
157c7cc5030SBrian Somers       prompt_TtyCommandMode(&prompt);
158c7cc5030SBrian Somers       prompt_nonewline = 0;
159c7cc5030SBrian Somers       /* We'll get a prompt because of our status change */
160c7cc5030SBrian Somers       /* Fall through */
161c7cc5030SBrian Somers 
162c7cc5030SBrian Somers     default:
163c7cc5030SBrian Somers       /* Wait 'till we're in a state we care about */
164c7cc5030SBrian Somers       return;
165c7cc5030SBrian Somers   }
166c7cc5030SBrian Somers 
16785b542cfSBrian Somers   /*
16885b542cfSBrian Somers    * We are in terminal mode, decode special sequences
16985b542cfSBrian Somers    */
17085b542cfSBrian Somers   n = read(p->fd_in, &ch, 1);
17185b542cfSBrian Somers   LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
17285b542cfSBrian Somers 
17385b542cfSBrian Somers   if (n > 0) {
17485b542cfSBrian Somers     switch (ttystate) {
17585b542cfSBrian Somers     case 0:
17685b542cfSBrian Somers       if (ch == '~')
17785b542cfSBrian Somers 	ttystate++;
17885b542cfSBrian Somers       else
17985b542cfSBrian Somers 	/* XXX missing return value check */
1803006ec67SBrian Somers 	Physical_Write(bundle2physical(bundle, NULL), &ch, n);
18185b542cfSBrian Somers       break;
18285b542cfSBrian Somers     case 1:
18385b542cfSBrian Somers       switch (ch) {
18485b542cfSBrian Somers       case '?':
18585b542cfSBrian Somers 	prompt_ShowHelp(p);
18685b542cfSBrian Somers 	break;
18785b542cfSBrian Somers       case 'p':
188c7cc5030SBrian Somers         datalink_Up(p->TermMode, 0, 1);
189c7cc5030SBrian Somers         prompt_Printf(p, "\nPacket mode.\n");
190c7cc5030SBrian Somers 	prompt_TtyCommandMode(&prompt);
19185b542cfSBrian Somers         break;
19285b542cfSBrian Somers       case '.':
19385b542cfSBrian Somers 	prompt_TtyCommandMode(&prompt);
19485b542cfSBrian Somers         prompt_nonewline = 0;
19585b542cfSBrian Somers         prompt_Display(&prompt, bundle);
19685b542cfSBrian Somers 	break;
19785b542cfSBrian Somers       case 't':
19885b542cfSBrian Somers 	if (LogIsKept(LogDEBUG)) {
19985b542cfSBrian Somers 	  ShowTimers();
20085b542cfSBrian Somers 	  break;
20185b542cfSBrian Somers 	}
20285b542cfSBrian Somers       case 'm':
20385b542cfSBrian Somers 	if (LogIsKept(LogDEBUG)) {
20485b542cfSBrian Somers 	  ShowMemMap(NULL);
20585b542cfSBrian Somers 	  break;
20685b542cfSBrian Somers 	}
20785b542cfSBrian Somers       default:
2083006ec67SBrian Somers 	if (Physical_Write(bundle2physical(bundle, NULL), &ch, n) < 0)
20985b542cfSBrian Somers 	  LogPrintf(LogERROR, "error writing to modem.\n");
21085b542cfSBrian Somers 	break;
21185b542cfSBrian Somers       }
21285b542cfSBrian Somers       ttystate = 0;
21385b542cfSBrian Somers       break;
21485b542cfSBrian Somers     }
21585b542cfSBrian Somers   }
21685b542cfSBrian Somers }
21785b542cfSBrian Somers 
21885b542cfSBrian Somers static void
219f4768038SBrian Somers prompt_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
22085b542cfSBrian Somers {
221f4768038SBrian Somers   /* We never want to write here ! */
222f4768038SBrian Somers   LogPrintf(LogERROR, "prompt_Write: Internal error: Bad call !\n");
22385b542cfSBrian Somers }
22485b542cfSBrian Somers 
22585b542cfSBrian Somers struct prompt prompt = {
22685b542cfSBrian Somers   {
22785b542cfSBrian Somers     PROMPT_DESCRIPTOR,
22885b542cfSBrian Somers     NULL,
22985b542cfSBrian Somers     prompt_UpdateSet,
23085b542cfSBrian Somers     prompt_IsSet,
23185b542cfSBrian Somers     prompt_Read,
23285b542cfSBrian Somers     prompt_Write
23385b542cfSBrian Somers   },
23485b542cfSBrian Somers   -1,
23585b542cfSBrian Somers   -1,
23685b542cfSBrian Somers   NULL
23785b542cfSBrian Somers };
23885b542cfSBrian Somers 
23985b542cfSBrian Somers int
24085b542cfSBrian Somers prompt_Init(struct prompt *p, int fd)
24185b542cfSBrian Somers {
24285b542cfSBrian Somers   if (p->Term && p->Term != stdout)
24385b542cfSBrian Somers     return 0;                       /* must prompt_Drop() first */
24485b542cfSBrian Somers 
24585b542cfSBrian Somers   if (fd == PROMPT_NONE) {
24685b542cfSBrian Somers     p->fd_in = p->fd_out = -1;
24785b542cfSBrian Somers     p->Term = NULL;
24885b542cfSBrian Somers   } else if (fd == PROMPT_STD) {
24985b542cfSBrian Somers     p->fd_in = STDIN_FILENO;
25085b542cfSBrian Somers     p->fd_out = STDOUT_FILENO;
25185b542cfSBrian Somers     p->Term = stdout;
25285b542cfSBrian Somers   } else {
25385b542cfSBrian Somers     p->fd_in = p->fd_out = fd;
25485b542cfSBrian Somers     p->Term = fdopen(fd, "a+");
25585b542cfSBrian Somers   }
2561b35f8f7SBrian Somers   p->TermMode = NULL;
25785b542cfSBrian Somers   tcgetattr(STDIN_FILENO, &p->oldtio);	/* Save original tty mode */
25885b542cfSBrian Somers 
25985b542cfSBrian Somers   return 1;
26085b542cfSBrian Somers }
26185b542cfSBrian Somers 
2623006ec67SBrian Somers void
26385b542cfSBrian Somers prompt_Display(struct prompt *p, struct bundle *bundle)
26485b542cfSBrian Somers {
26585b542cfSBrian Somers   const char *pconnect, *pauth;
26685b542cfSBrian Somers 
2671b35f8f7SBrian Somers   if (!p->Term || p->TermMode != NULL || CleaningUp)
26885b542cfSBrian Somers     return;
26985b542cfSBrian Somers 
27085b542cfSBrian Somers   if (prompt_nonewline)
27185b542cfSBrian Somers     prompt_nonewline = 0;
27285b542cfSBrian Somers   else
27385b542cfSBrian Somers     fprintf(p->Term, "\n");
27485b542cfSBrian Somers 
27585b542cfSBrian Somers   if (VarLocalAuth == LOCAL_AUTH)
27685b542cfSBrian Somers     pauth = " ON ";
27785b542cfSBrian Somers   else
27885b542cfSBrian Somers     pauth = " on ";
27985b542cfSBrian Somers 
28085b542cfSBrian Somers   if (IpcpInfo.fsm.state == ST_OPENED)
28185b542cfSBrian Somers     pconnect = "PPP";
28285b542cfSBrian Somers   else if (bundle_Phase(bundle) == PHASE_NETWORK)
28385b542cfSBrian Somers     pconnect = "PPp";
28485b542cfSBrian Somers   else if (bundle_Phase(bundle) == PHASE_AUTHENTICATE)
28585b542cfSBrian Somers     pconnect = "Ppp";
28685b542cfSBrian Somers   else
28785b542cfSBrian Somers     pconnect = "ppp";
28885b542cfSBrian Somers 
28985b542cfSBrian Somers   fprintf(p->Term, "%s%s%s> ", pconnect, pauth, VarShortHost);
29085b542cfSBrian Somers   fflush(p->Term);
29185b542cfSBrian Somers }
29285b542cfSBrian Somers 
29385b542cfSBrian Somers void
29485b542cfSBrian Somers prompt_Drop(struct prompt *p, int verbose)
29585b542cfSBrian Somers {
29685b542cfSBrian Somers   if (p->Term && p->Term != stdout) {
29785b542cfSBrian Somers     FILE *oVarTerm;
29885b542cfSBrian Somers 
29985b542cfSBrian Somers     oVarTerm = p->Term;
30085b542cfSBrian Somers     p->Term = NULL;
30185b542cfSBrian Somers     if (oVarTerm)
30285b542cfSBrian Somers       fclose(oVarTerm);
30385b542cfSBrian Somers     close(p->fd_in);
30485b542cfSBrian Somers     if (p->fd_out != p->fd_in)
30585b542cfSBrian Somers       close(p->fd_out);
30685b542cfSBrian Somers     p->fd_in = p->fd_out = -1;
30785b542cfSBrian Somers     if (verbose)
30885b542cfSBrian Somers       LogPrintf(LogPHASE, "Client connection dropped.\n");
30985b542cfSBrian Somers   }
31085b542cfSBrian Somers }
31185b542cfSBrian Somers 
31285b542cfSBrian Somers void
31385b542cfSBrian Somers prompt_Printf(struct prompt *p, const char *fmt,...)
31485b542cfSBrian Somers {
31585b542cfSBrian Somers   if (p->Term) {
31685b542cfSBrian Somers     va_list ap;
31785b542cfSBrian Somers 
31885b542cfSBrian Somers     va_start(ap, fmt);
31985b542cfSBrian Somers     vfprintf(p->Term, fmt, ap);
32085b542cfSBrian Somers     fflush(p->Term);
32185b542cfSBrian Somers     va_end(ap);
32285b542cfSBrian Somers   }
32385b542cfSBrian Somers }
32485b542cfSBrian Somers 
32585b542cfSBrian Somers void
32685b542cfSBrian Somers prompt_vPrintf(struct prompt *p, const char *fmt, va_list ap)
32785b542cfSBrian Somers {
32885b542cfSBrian Somers   if (p->Term) {
32985b542cfSBrian Somers     vfprintf(p->Term, fmt, ap);
33085b542cfSBrian Somers     fflush(p->Term);
33185b542cfSBrian Somers   }
33285b542cfSBrian Somers }
33385b542cfSBrian Somers 
33485b542cfSBrian Somers void
33585b542cfSBrian Somers prompt_TtyInit(struct prompt *p, int DontWantInt)
33685b542cfSBrian Somers {
33785b542cfSBrian Somers   struct termios newtio;
33885b542cfSBrian Somers   int stat;
33985b542cfSBrian Somers 
34085b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
34185b542cfSBrian Somers   if (stat > 0) {
34285b542cfSBrian Somers     stat |= O_NONBLOCK;
34385b542cfSBrian Somers     (void) fcntl(p->fd_in, F_SETFL, stat);
34485b542cfSBrian Somers   }
34585b542cfSBrian Somers   newtio = p->oldtio;
34685b542cfSBrian Somers   newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
34785b542cfSBrian Somers   newtio.c_iflag = 0;
34885b542cfSBrian Somers   newtio.c_oflag &= ~OPOST;
34985b542cfSBrian Somers   newtio.c_cc[VEOF] = _POSIX_VDISABLE;
35085b542cfSBrian Somers   if (DontWantInt)
35185b542cfSBrian Somers     newtio.c_cc[VINTR] = _POSIX_VDISABLE;
35285b542cfSBrian Somers   newtio.c_cc[VMIN] = 1;
35385b542cfSBrian Somers   newtio.c_cc[VTIME] = 0;
35485b542cfSBrian Somers   newtio.c_cflag |= CS8;
35585b542cfSBrian Somers   tcsetattr(p->fd_in, TCSANOW, &newtio);
35685b542cfSBrian Somers   p->comtio = newtio;
35785b542cfSBrian Somers }
35885b542cfSBrian Somers 
35985b542cfSBrian Somers /*
36085b542cfSBrian Somers  *  Set tty into command mode. We allow canonical input and echo processing.
36185b542cfSBrian Somers  */
36285b542cfSBrian Somers void
36385b542cfSBrian Somers prompt_TtyCommandMode(struct prompt *p)
36485b542cfSBrian Somers {
36585b542cfSBrian Somers   struct termios newtio;
36685b542cfSBrian Somers   int stat;
36785b542cfSBrian Somers 
36885b542cfSBrian Somers   if (!(mode & MODE_INTER))
36985b542cfSBrian Somers     return;
37085b542cfSBrian Somers 
37185b542cfSBrian Somers   tcgetattr(p->fd_in, &newtio);
37285b542cfSBrian Somers   newtio.c_lflag |= (ECHO | ISIG | ICANON);
37385b542cfSBrian Somers   newtio.c_iflag = p->oldtio.c_iflag;
37485b542cfSBrian Somers   newtio.c_oflag |= OPOST;
37585b542cfSBrian Somers   tcsetattr(p->fd_in, TCSADRAIN, &newtio);
37685b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
37785b542cfSBrian Somers   if (stat > 0) {
37885b542cfSBrian Somers     stat |= O_NONBLOCK;
37985b542cfSBrian Somers     (void) fcntl(p->fd_in, F_SETFL, stat);
38085b542cfSBrian Somers   }
3811b35f8f7SBrian Somers   p->TermMode = NULL;
38285b542cfSBrian Somers }
38385b542cfSBrian Somers 
38485b542cfSBrian Somers /*
38585b542cfSBrian Somers  * Set tty into terminal mode which is used while we invoke term command.
38685b542cfSBrian Somers  */
38785b542cfSBrian Somers void
3881b35f8f7SBrian Somers prompt_TtyTermMode(struct prompt *p, struct datalink *dl)
38985b542cfSBrian Somers {
39085b542cfSBrian Somers   int stat;
39185b542cfSBrian Somers 
39285b542cfSBrian Somers   tcsetattr(p->fd_in, TCSADRAIN, &p->comtio);
39385b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
39485b542cfSBrian Somers   if (stat > 0) {
39585b542cfSBrian Somers     stat &= ~O_NONBLOCK;
39685b542cfSBrian Somers     (void) fcntl(p->fd_in, F_SETFL, stat);
39785b542cfSBrian Somers   }
3981b35f8f7SBrian Somers   p->TermMode = dl;
39985b542cfSBrian Somers }
40085b542cfSBrian Somers 
40185b542cfSBrian Somers void
40285b542cfSBrian Somers prompt_TtyOldMode(struct prompt *p)
40385b542cfSBrian Somers {
40485b542cfSBrian Somers   int stat;
40585b542cfSBrian Somers 
40685b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
40785b542cfSBrian Somers   if (stat > 0) {
40885b542cfSBrian Somers     stat &= ~O_NONBLOCK;
40985b542cfSBrian Somers     (void) fcntl(p->fd_in, F_SETFL, stat);
41085b542cfSBrian Somers   }
41185b542cfSBrian Somers   tcsetattr(p->fd_in, TCSADRAIN, &p->oldtio);
41285b542cfSBrian Somers }
41385b542cfSBrian Somers 
41485b542cfSBrian Somers pid_t
41585b542cfSBrian Somers prompt_pgrp(struct prompt *p)
41685b542cfSBrian Somers {
41785b542cfSBrian Somers   return p->Term ? tcgetpgrp(p->fd_in) : -1;
41885b542cfSBrian Somers }
419