xref: /freebsd/usr.sbin/ppp/prompt.c (revision 833882f74089dd21e429d7033ace6b5db16dfbb7)
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  *
26833882f7SBrian Somers  *	$Id: prompt.c,v 1.1.2.18 1998/04/03 19:25:50 brian Exp $
2785b542cfSBrian Somers  */
2885b542cfSBrian Somers 
2985b542cfSBrian Somers #include <sys/param.h>
3085b542cfSBrian Somers #include <netinet/in.h>
31eaa4df37SBrian Somers #include <netinet/in_systm.h>
32eaa4df37SBrian Somers #include <netinet/ip.h>
3385b542cfSBrian Somers 
34833882f7SBrian Somers #include <errno.h>
3585b542cfSBrian Somers #include <stdarg.h>
3685b542cfSBrian Somers #include <stdio.h>
37b6217683SBrian Somers #include <stdlib.h>
38b6217683SBrian Somers #include <string.h>
3985b542cfSBrian Somers #include <sys/fcntl.h>
4085b542cfSBrian Somers #include <sys/stat.h>
4185b542cfSBrian Somers #include <termios.h>
4285b542cfSBrian Somers #include <unistd.h>
4385b542cfSBrian Somers 
4485b542cfSBrian Somers #include "defs.h"
4585b542cfSBrian Somers #include "timer.h"
4685b542cfSBrian Somers #include "command.h"
4785b542cfSBrian Somers #include "log.h"
4885b542cfSBrian Somers #include "descriptor.h"
4985b542cfSBrian Somers #include "prompt.h"
5085b542cfSBrian Somers #include "fsm.h"
5185b542cfSBrian Somers #include "lcp.h"
5285b542cfSBrian Somers #include "auth.h"
5385b542cfSBrian Somers #include "loadalias.h"
5485b542cfSBrian Somers #include "vars.h"
5585b542cfSBrian Somers #include "main.h"
5685b542cfSBrian Somers #include "iplist.h"
5785b542cfSBrian Somers #include "throughput.h"
58eaa4df37SBrian Somers #include "slcompress.h"
5985b542cfSBrian Somers #include "ipcp.h"
605ca5389aSBrian Somers #include "filter.h"
61879ed6faSBrian Somers #include "lqr.h"
623006ec67SBrian Somers #include "hdlc.h"
633006ec67SBrian Somers #include "async.h"
643006ec67SBrian Somers #include "mbuf.h"
653b0f8d2eSBrian Somers #include "ccp.h"
663006ec67SBrian Somers #include "link.h"
673006ec67SBrian Somers #include "physical.h"
683b0f8d2eSBrian Somers #include "mp.h"
693b0f8d2eSBrian Somers #include "bundle.h"
70c5a5a6caSBrian Somers #include "chat.h"
71e2ebb036SBrian Somers #include "chap.h"
72c5a5a6caSBrian Somers #include "datalink.h"
73b6217683SBrian Somers #include "server.h"
7485b542cfSBrian Somers 
75b6217683SBrian Somers static void
76b6217683SBrian Somers prompt_Display(struct prompt *p)
77b6217683SBrian Somers {
78b6217683SBrian Somers   static char shostname[MAXHOSTNAMELEN];
79b6217683SBrian Somers   const char *pconnect, *pauth;
80b6217683SBrian Somers 
81b6217683SBrian Somers   if (p->TermMode || !p->needprompt)
82b6217683SBrian Somers     return;
83b6217683SBrian Somers 
84b6217683SBrian Somers   p->needprompt = 0;
85b6217683SBrian Somers 
86b6217683SBrian Somers   if (p->nonewline)
87b6217683SBrian Somers     p->nonewline = 0;
88b6217683SBrian Somers   else
89b6217683SBrian Somers     fprintf(p->Term, "\n");
90b6217683SBrian Somers 
91b6217683SBrian Somers   if (p->auth == LOCAL_AUTH)
92b6217683SBrian Somers     pauth = " ON ";
93b6217683SBrian Somers   else
94b6217683SBrian Somers     pauth = " on ";
95b6217683SBrian Somers 
96b6217683SBrian Somers   if (p->bundle->ncp.ipcp.fsm.state == ST_OPENED)
97b6217683SBrian Somers     pconnect = "PPP";
98b6217683SBrian Somers   else if (bundle_Phase(p->bundle) == PHASE_NETWORK)
99b6217683SBrian Somers     pconnect = "PPp";
100b6217683SBrian Somers   else if (bundle_Phase(p->bundle) == PHASE_AUTHENTICATE)
101b6217683SBrian Somers     pconnect = "Ppp";
102b6217683SBrian Somers   else
103b6217683SBrian Somers     pconnect = "ppp";
104b6217683SBrian Somers 
105b6217683SBrian Somers   if (*shostname == '\0') {
106b6217683SBrian Somers     char *p;
107b6217683SBrian Somers 
108b6217683SBrian Somers     if (gethostname(shostname, sizeof shostname))
109b6217683SBrian Somers       strcpy(shostname, "localhost");
110b6217683SBrian Somers     else if ((p = strchr(shostname, '.')))
111b6217683SBrian Somers       *p = '\0';
112b6217683SBrian Somers   }
113b6217683SBrian Somers 
114b6217683SBrian Somers   fprintf(p->Term, "%s%s%s> ", pconnect, pauth, shostname);
115b6217683SBrian Somers   fflush(p->Term);
116b6217683SBrian Somers }
11785b542cfSBrian Somers 
11885b542cfSBrian Somers static int
11985b542cfSBrian Somers prompt_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
12085b542cfSBrian Somers {
12185b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
122b6dec9f0SBrian Somers   int sets;
12385b542cfSBrian Somers 
124b6dec9f0SBrian Somers   sets = 0;
12585b542cfSBrian Somers   if (p->fd_in >= 0) {
126b6dec9f0SBrian Somers     if (r) {
12785b542cfSBrian Somers       FD_SET(p->fd_in, r);
128b6dec9f0SBrian Somers       sets++;
129b6dec9f0SBrian Somers     }
130b6dec9f0SBrian Somers     if (e) {
13185b542cfSBrian Somers       FD_SET(p->fd_in, e);
132b6dec9f0SBrian Somers       sets++;
133b6dec9f0SBrian Somers     }
134b6dec9f0SBrian Somers     if (sets && *n < p->fd_in + 1)
135b6dec9f0SBrian Somers       *n = p->fd_in + 1;
13685b542cfSBrian Somers   }
13785b542cfSBrian Somers 
138b6217683SBrian Somers   prompt_Display(p);
139b6217683SBrian Somers 
140b6dec9f0SBrian Somers   return sets;
14185b542cfSBrian Somers }
14285b542cfSBrian Somers 
14385b542cfSBrian Somers static int
1442f786681SBrian Somers prompt_IsSet(struct descriptor *d, const fd_set *fdset)
14585b542cfSBrian Somers {
14685b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
14785b542cfSBrian Somers   return p->fd_in >= 0 && FD_ISSET(p->fd_in, fdset);
14885b542cfSBrian Somers }
14985b542cfSBrian Somers 
15085b542cfSBrian Somers 
15185b542cfSBrian Somers static void
15285b542cfSBrian Somers prompt_ShowHelp(struct prompt *p)
15385b542cfSBrian Somers {
15485b542cfSBrian Somers   prompt_Printf(p, "The following commands are available:\r\n");
15585b542cfSBrian Somers   prompt_Printf(p, " ~p\tEnter Packet mode\r\n");
15685b542cfSBrian Somers   prompt_Printf(p, " ~-\tDecrease log level\r\n");
15785b542cfSBrian Somers   prompt_Printf(p, " ~+\tIncrease log level\r\n");
1583b0f8d2eSBrian Somers   prompt_Printf(p, " ~t\tShow timers\r\n");
1593b0f8d2eSBrian Somers   prompt_Printf(p, " ~m\tShow memory map\r\n");
16085b542cfSBrian Somers   prompt_Printf(p, " ~.\tTerminate program\r\n");
16185b542cfSBrian Somers   prompt_Printf(p, " ~?\tThis help\r\n");
16285b542cfSBrian Somers }
16385b542cfSBrian Somers 
16485b542cfSBrian Somers static void
16585b542cfSBrian Somers prompt_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
16685b542cfSBrian Somers {
16785b542cfSBrian Somers   struct prompt *p = descriptor2prompt(d);
16885b542cfSBrian Somers   int n;
16985b542cfSBrian Somers   char ch;
17085b542cfSBrian Somers   static int ttystate;
17185b542cfSBrian Somers   char linebuff[LINE_LEN];
17285b542cfSBrian Somers 
1731b35f8f7SBrian Somers   LogPrintf(LogDEBUG, "termode = %p, p->fd_in = %d, mode = %d\n",
17485b542cfSBrian Somers 	    p->TermMode, p->fd_in, mode);
17585b542cfSBrian Somers 
1761b35f8f7SBrian Somers   if (p->TermMode == NULL) {
17785b542cfSBrian Somers     n = read(p->fd_in, linebuff, sizeof linebuff - 1);
17885b542cfSBrian Somers     if (n > 0) {
17985b542cfSBrian Somers       if (linebuff[n-1] == '\n')
18085b542cfSBrian Somers         linebuff[--n] = '\0';
18185b542cfSBrian Somers       else
18285b542cfSBrian Somers         linebuff[n] = '\0';
183b6217683SBrian Somers       p->nonewline = 1;		/* Maybe DecodeCommand does a prompt */
184b6217683SBrian Somers       prompt_Required(p);
18585b542cfSBrian Somers       if (n)
186b6217683SBrian Somers         DecodeCommand(bundle, linebuff, n, p,
187b6217683SBrian Somers                       IsInteractive(NULL) ? NULL : "Client");
18885b542cfSBrian Somers     } else if (n <= 0) {
18985b542cfSBrian Somers       LogPrintf(LogPHASE, "Client connection closed.\n");
190b6217683SBrian Somers       prompt_Destroy(p, 0);
19185b542cfSBrian Somers     }
19285b542cfSBrian Somers     return;
19385b542cfSBrian Somers   }
19485b542cfSBrian Somers 
195c7cc5030SBrian Somers   switch (p->TermMode->state) {
196c7cc5030SBrian Somers     case DATALINK_CLOSED:
197c7cc5030SBrian Somers       prompt_Printf(p, "Link lost, terminal mode.\n");
198b6217683SBrian Somers       prompt_TtyCommandMode(p);
199b6217683SBrian Somers       p->nonewline = 0;
200b6217683SBrian Somers       prompt_Required(p);
201c7cc5030SBrian Somers       return;
202c7cc5030SBrian Somers 
203c7cc5030SBrian Somers     case DATALINK_READY:
204c7cc5030SBrian Somers       break;
205c7cc5030SBrian Somers 
206c7cc5030SBrian Somers     case DATALINK_OPEN:
207c7cc5030SBrian Somers       prompt_Printf(p, "\nPacket mode detected.\n");
208b6217683SBrian Somers       prompt_TtyCommandMode(p);
209b6217683SBrian Somers       p->nonewline = 0;
210c7cc5030SBrian Somers       /* We'll get a prompt because of our status change */
211c7cc5030SBrian Somers       /* Fall through */
212c7cc5030SBrian Somers 
213c7cc5030SBrian Somers     default:
214c7cc5030SBrian Somers       /* Wait 'till we're in a state we care about */
215c7cc5030SBrian Somers       return;
216c7cc5030SBrian Somers   }
217c7cc5030SBrian Somers 
21885b542cfSBrian Somers   /*
21985b542cfSBrian Somers    * We are in terminal mode, decode special sequences
22085b542cfSBrian Somers    */
22185b542cfSBrian Somers   n = read(p->fd_in, &ch, 1);
22285b542cfSBrian Somers   LogPrintf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n);
22385b542cfSBrian Somers 
22485b542cfSBrian Somers   if (n > 0) {
22585b542cfSBrian Somers     switch (ttystate) {
22685b542cfSBrian Somers     case 0:
22785b542cfSBrian Somers       if (ch == '~')
22885b542cfSBrian Somers 	ttystate++;
22985b542cfSBrian Somers       else
230833882f7SBrian Somers 	if (Physical_Write(p->TermMode->physical, &ch, n) < 0) {
231833882f7SBrian Somers 	  LogPrintf(LogERROR, "error writing to modem: %s\n", strerror(errno));
232833882f7SBrian Somers           prompt_TtyCommandMode(p);
233833882f7SBrian Somers         }
23485b542cfSBrian Somers       break;
23585b542cfSBrian Somers     case 1:
23685b542cfSBrian Somers       switch (ch) {
23785b542cfSBrian Somers       case '?':
23885b542cfSBrian Somers 	prompt_ShowHelp(p);
23985b542cfSBrian Somers 	break;
24085b542cfSBrian Somers       case 'p':
241c7cc5030SBrian Somers         datalink_Up(p->TermMode, 0, 1);
242c7cc5030SBrian Somers         prompt_Printf(p, "\nPacket mode.\n");
243b6217683SBrian Somers 	prompt_TtyCommandMode(p);
24485b542cfSBrian Somers         break;
24585b542cfSBrian Somers       case '.':
246b6217683SBrian Somers 	prompt_TtyCommandMode(p);
247b6217683SBrian Somers         p->nonewline = 0;
248b6217683SBrian Somers         prompt_Required(p);
24985b542cfSBrian Somers 	break;
25085b542cfSBrian Somers       case 't':
251b6217683SBrian Somers 	ShowTimers(0, p);
25285b542cfSBrian Somers 	break;
25385b542cfSBrian Somers       case 'm':
25485b542cfSBrian Somers 	ShowMemMap(NULL);
25585b542cfSBrian Somers 	break;
25685b542cfSBrian Somers       default:
257833882f7SBrian Somers 	if (Physical_Write(p->TermMode->physical, &ch, n) < 0) {
258833882f7SBrian Somers 	  LogPrintf(LogERROR, "error writing to modem: %s\n", strerror(errno));
259833882f7SBrian Somers           prompt_TtyCommandMode(p);
260833882f7SBrian Somers         }
26185b542cfSBrian Somers 	break;
26285b542cfSBrian Somers       }
26385b542cfSBrian Somers       ttystate = 0;
26485b542cfSBrian Somers       break;
26585b542cfSBrian Somers     }
26685b542cfSBrian Somers   }
26785b542cfSBrian Somers }
26885b542cfSBrian Somers 
26985b542cfSBrian Somers static void
270f4768038SBrian Somers prompt_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
27185b542cfSBrian Somers {
272f4768038SBrian Somers   /* We never want to write here ! */
273f4768038SBrian Somers   LogPrintf(LogERROR, "prompt_Write: Internal error: Bad call !\n");
27485b542cfSBrian Somers }
27585b542cfSBrian Somers 
276b6217683SBrian Somers struct prompt *
277b6217683SBrian Somers prompt_Create(struct server *s, struct bundle *bundle, int fd)
27885b542cfSBrian Somers {
279b6217683SBrian Somers   struct prompt *p = (struct prompt *)malloc(sizeof(struct prompt));
28085b542cfSBrian Somers 
281b6217683SBrian Somers   if (p != NULL) {
282b6217683SBrian Somers     p->desc.type = PROMPT_DESCRIPTOR;
283b6217683SBrian Somers     p->desc.next = NULL;
284b6217683SBrian Somers     p->desc.UpdateSet = prompt_UpdateSet;
285b6217683SBrian Somers     p->desc.IsSet = prompt_IsSet;
286b6217683SBrian Somers     p->desc.Read = prompt_Read;
287b6217683SBrian Somers     p->desc.Write = prompt_Write;
28885b542cfSBrian Somers 
289b6217683SBrian Somers     if (fd == PROMPT_STD) {
29085b542cfSBrian Somers       p->fd_in = STDIN_FILENO;
29185b542cfSBrian Somers       p->fd_out = STDOUT_FILENO;
29285b542cfSBrian Somers       p->Term = stdout;
293b6217683SBrian Somers       p->owner = NULL;
294b6217683SBrian Somers       p->auth = LOCAL_AUTH;
295b6217683SBrian Somers       snprintf(p->who, sizeof p->who, "Controller (%s)", ttyname(p->fd_out));
296b6217683SBrian Somers       tcgetattr(p->fd_in, &p->oldtio);	/* Save original tty mode */
29785b542cfSBrian Somers     } else {
29885b542cfSBrian Somers       p->fd_in = p->fd_out = fd;
29985b542cfSBrian Somers       p->Term = fdopen(fd, "a+");
300b6217683SBrian Somers       p->owner = s;
301b6217683SBrian Somers       p->auth = *s->passwd ? LOCAL_NO_AUTH : LOCAL_AUTH;
302b6217683SBrian Somers       *p->who = '\0';
30385b542cfSBrian Somers     }
3041b35f8f7SBrian Somers     p->TermMode = NULL;
305b6217683SBrian Somers     p->nonewline = 1;
306b6217683SBrian Somers     p->needprompt = 1;
307b6217683SBrian Somers     p->bundle = bundle;
308b6217683SBrian Somers     if (p->bundle)
309b6217683SBrian Somers       bundle_RegisterDescriptor(p->bundle, &p->desc);
310b6217683SBrian Somers     log_RegisterPrompt(p);
311b6217683SBrian Somers   }
31285b542cfSBrian Somers 
313b6217683SBrian Somers   return p;
31485b542cfSBrian Somers }
31585b542cfSBrian Somers 
3163006ec67SBrian Somers void
317b6217683SBrian Somers prompt_DestroyUnclean(struct prompt *p)
31885b542cfSBrian Somers {
319b6217683SBrian Somers   log_UnRegisterPrompt(p);
320b6217683SBrian Somers   bundle_UnRegisterDescriptor(p->bundle, &p->desc);
321b6217683SBrian Somers   free(p);
32285b542cfSBrian Somers }
32385b542cfSBrian Somers 
32485b542cfSBrian Somers void
325b6217683SBrian Somers prompt_Destroy(struct prompt *p, int verbose)
32685b542cfSBrian Somers {
327b6217683SBrian Somers   if (p->Term != stdout) {
328b6217683SBrian Somers     fclose(p->Term);
32985b542cfSBrian Somers     close(p->fd_in);
33085b542cfSBrian Somers     if (p->fd_out != p->fd_in)
33185b542cfSBrian Somers       close(p->fd_out);
33285b542cfSBrian Somers     if (verbose)
33385b542cfSBrian Somers       LogPrintf(LogPHASE, "Client connection dropped.\n");
334b6217683SBrian Somers   } else
335b6217683SBrian Somers     prompt_TtyOldMode(p);
336b6217683SBrian Somers 
337b6217683SBrian Somers   prompt_DestroyUnclean(p);
33885b542cfSBrian Somers }
33985b542cfSBrian Somers 
34085b542cfSBrian Somers void
34185b542cfSBrian Somers prompt_Printf(struct prompt *p, const char *fmt,...)
34285b542cfSBrian Somers {
343b6217683SBrian Somers   if (p) {
34485b542cfSBrian Somers     va_list ap;
34585b542cfSBrian Somers 
34685b542cfSBrian Somers     va_start(ap, fmt);
34785b542cfSBrian Somers     vfprintf(p->Term, fmt, ap);
34885b542cfSBrian Somers     fflush(p->Term);
34985b542cfSBrian Somers     va_end(ap);
35085b542cfSBrian Somers   }
35185b542cfSBrian Somers }
35285b542cfSBrian Somers 
35385b542cfSBrian Somers void
35485b542cfSBrian Somers prompt_vPrintf(struct prompt *p, const char *fmt, va_list ap)
35585b542cfSBrian Somers {
356b6217683SBrian Somers   if (p) {
35785b542cfSBrian Somers     vfprintf(p->Term, fmt, ap);
35885b542cfSBrian Somers     fflush(p->Term);
35985b542cfSBrian Somers   }
36085b542cfSBrian Somers }
36185b542cfSBrian Somers 
36285b542cfSBrian Somers void
36385b542cfSBrian Somers prompt_TtyInit(struct prompt *p, int DontWantInt)
36485b542cfSBrian Somers {
36585b542cfSBrian Somers   int stat;
36685b542cfSBrian Somers 
36785b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
36885b542cfSBrian Somers   if (stat > 0) {
36985b542cfSBrian Somers     stat |= O_NONBLOCK;
370b6217683SBrian Somers     fcntl(p->fd_in, F_SETFL, stat);
37185b542cfSBrian Somers   }
372b6217683SBrian Somers 
373b6217683SBrian Somers   if (p->Term == stdout) {
374b6217683SBrian Somers     struct termios newtio;
375b6217683SBrian Somers 
37685b542cfSBrian Somers     newtio = p->oldtio;
37785b542cfSBrian Somers     newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
37885b542cfSBrian Somers     newtio.c_iflag = 0;
37985b542cfSBrian Somers     newtio.c_oflag &= ~OPOST;
38085b542cfSBrian Somers     newtio.c_cc[VEOF] = _POSIX_VDISABLE;
38185b542cfSBrian Somers     if (DontWantInt)
38285b542cfSBrian Somers       newtio.c_cc[VINTR] = _POSIX_VDISABLE;
38385b542cfSBrian Somers     newtio.c_cc[VMIN] = 1;
38485b542cfSBrian Somers     newtio.c_cc[VTIME] = 0;
38585b542cfSBrian Somers     newtio.c_cflag |= CS8;
38685b542cfSBrian Somers     tcsetattr(p->fd_in, TCSANOW, &newtio);
38785b542cfSBrian Somers     p->comtio = newtio;
38885b542cfSBrian Somers   }
389b6217683SBrian Somers }
39085b542cfSBrian Somers 
39185b542cfSBrian Somers /*
39285b542cfSBrian Somers  *  Set tty into command mode. We allow canonical input and echo processing.
39385b542cfSBrian Somers  */
39485b542cfSBrian Somers void
39585b542cfSBrian Somers prompt_TtyCommandMode(struct prompt *p)
39685b542cfSBrian Somers {
39785b542cfSBrian Somers   struct termios newtio;
39885b542cfSBrian Somers   int stat;
39985b542cfSBrian Somers 
40085b542cfSBrian Somers   tcgetattr(p->fd_in, &newtio);
40185b542cfSBrian Somers   newtio.c_lflag |= (ECHO | ISIG | ICANON);
40285b542cfSBrian Somers   newtio.c_iflag = p->oldtio.c_iflag;
40385b542cfSBrian Somers   newtio.c_oflag |= OPOST;
40485b542cfSBrian Somers   tcsetattr(p->fd_in, TCSADRAIN, &newtio);
405b6217683SBrian Somers 
40685b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
40785b542cfSBrian Somers   if (stat > 0) {
40885b542cfSBrian Somers     stat |= O_NONBLOCK;
409b6217683SBrian Somers     fcntl(p->fd_in, F_SETFL, stat);
41085b542cfSBrian Somers   }
411b6217683SBrian Somers 
4121b35f8f7SBrian Somers   p->TermMode = NULL;
41385b542cfSBrian Somers }
41485b542cfSBrian Somers 
41585b542cfSBrian Somers /*
41685b542cfSBrian Somers  * Set tty into terminal mode which is used while we invoke term command.
41785b542cfSBrian Somers  */
41885b542cfSBrian Somers void
4191b35f8f7SBrian Somers prompt_TtyTermMode(struct prompt *p, struct datalink *dl)
42085b542cfSBrian Somers {
42185b542cfSBrian Somers   int stat;
42285b542cfSBrian Somers 
423b6217683SBrian Somers   prompt_Printf(p, "Entering terminal mode on %s.\n", dl->name);
424b6217683SBrian Somers   prompt_Printf(p, "Type `~?' for help.\n");
425b6217683SBrian Somers 
426b6217683SBrian Somers   if (p->Term == stdout)
42785b542cfSBrian Somers     tcsetattr(p->fd_in, TCSADRAIN, &p->comtio);
428b6217683SBrian Somers 
42985b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
43085b542cfSBrian Somers   if (stat > 0) {
43185b542cfSBrian Somers     stat &= ~O_NONBLOCK;
432b6217683SBrian Somers     fcntl(p->fd_in, F_SETFL, stat);
43385b542cfSBrian Somers   }
4341b35f8f7SBrian Somers   p->TermMode = dl;
43585b542cfSBrian Somers }
43685b542cfSBrian Somers 
43785b542cfSBrian Somers void
43885b542cfSBrian Somers prompt_TtyOldMode(struct prompt *p)
43985b542cfSBrian Somers {
44085b542cfSBrian Somers   int stat;
44185b542cfSBrian Somers 
44285b542cfSBrian Somers   stat = fcntl(p->fd_in, F_GETFL, 0);
44385b542cfSBrian Somers   if (stat > 0) {
44485b542cfSBrian Somers     stat &= ~O_NONBLOCK;
445b6217683SBrian Somers     fcntl(p->fd_in, F_SETFL, stat);
44685b542cfSBrian Somers   }
447b6217683SBrian Somers 
448b6217683SBrian Somers   if (p->Term == stdout)
44985b542cfSBrian Somers     tcsetattr(p->fd_in, TCSADRAIN, &p->oldtio);
45085b542cfSBrian Somers }
45185b542cfSBrian Somers 
45285b542cfSBrian Somers pid_t
45385b542cfSBrian Somers prompt_pgrp(struct prompt *p)
45485b542cfSBrian Somers {
455b6217683SBrian Somers   return tcgetpgrp(p->fd_in);
456b6217683SBrian Somers }
457b6217683SBrian Somers 
458b6217683SBrian Somers int
459b6217683SBrian Somers PasswdCommand(struct cmdargs const *arg)
460b6217683SBrian Somers {
461b6217683SBrian Somers   const char *pass;
462b6217683SBrian Somers 
463b6217683SBrian Somers   if (!arg->prompt) {
464b6217683SBrian Somers     LogPrintf(LogWARN, "passwd: Cannot specify without a prompt\n");
465b6217683SBrian Somers     return 0;
466b6217683SBrian Somers   }
467b6217683SBrian Somers 
468b6217683SBrian Somers   if (arg->prompt->owner == NULL) {
469b6217683SBrian Somers     LogPrintf(LogWARN, "passwd: Not required\n");
470b6217683SBrian Somers     return 0;
471b6217683SBrian Somers   }
472b6217683SBrian Somers 
473b6217683SBrian Somers   if (arg->argc == 0)
474b6217683SBrian Somers     pass = "";
475b6217683SBrian Somers   else if (arg->argc > 1)
476b6217683SBrian Somers     return -1;
477b6217683SBrian Somers   else
478b6217683SBrian Somers     pass = *arg->argv;
479b6217683SBrian Somers 
480b6217683SBrian Somers   if (!strcmp(arg->prompt->owner->passwd, pass))
481b6217683SBrian Somers     arg->prompt->auth = LOCAL_AUTH;
482b6217683SBrian Somers   else
483b6217683SBrian Somers     arg->prompt->auth = LOCAL_NO_AUTH;
484b6217683SBrian Somers 
485b6217683SBrian Somers   return 0;
48685b542cfSBrian Somers }
487