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