prompt.c (3b0f8d2ed641ceeded11c0d3f253b0cacbf00880) prompt.c (b6217683dc0269a53b799399522dbdfb5a4919cc)
1/*-
2 * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: prompt.c,v 1.1.2.16 1998/03/20 19:48:19 brian Exp $
26 * $Id: prompt.c,v 1.1.2.17 1998/04/03 19:21:50 brian Exp $
27 */
28
29#include <sys/param.h>
30#include <netinet/in.h>
31#include <netinet/in_systm.h>
32#include <netinet/ip.h>
33
34#include <stdarg.h>
35#include <stdio.h>
27 */
28
29#include <sys/param.h>
30#include <netinet/in.h>
31#include <netinet/in_systm.h>
32#include <netinet/ip.h>
33
34#include <stdarg.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
36#include <sys/fcntl.h>
37#include <sys/stat.h>
38#include <termios.h>
39#include <unistd.h>
40
41#include "defs.h"
42#include "timer.h"
43#include "command.h"

--- 18 unchanged lines hidden (view full) ---

62#include "ccp.h"
63#include "link.h"
64#include "physical.h"
65#include "mp.h"
66#include "bundle.h"
67#include "chat.h"
68#include "chap.h"
69#include "datalink.h"
38#include <sys/fcntl.h>
39#include <sys/stat.h>
40#include <termios.h>
41#include <unistd.h>
42
43#include "defs.h"
44#include "timer.h"
45#include "command.h"

--- 18 unchanged lines hidden (view full) ---

64#include "ccp.h"
65#include "link.h"
66#include "physical.h"
67#include "mp.h"
68#include "bundle.h"
69#include "chat.h"
70#include "chap.h"
71#include "datalink.h"
72#include "server.h"
70
73
71static int prompt_nonewline = 1;
74static void
75prompt_Display(struct prompt *p)
76{
77 static char shostname[MAXHOSTNAMELEN];
78 const char *pconnect, *pauth;
72
79
80 if (p->TermMode || !p->needprompt)
81 return;
82
83 p->needprompt = 0;
84
85 if (p->nonewline)
86 p->nonewline = 0;
87 else
88 fprintf(p->Term, "\n");
89
90 if (p->auth == LOCAL_AUTH)
91 pauth = " ON ";
92 else
93 pauth = " on ";
94
95 if (p->bundle->ncp.ipcp.fsm.state == ST_OPENED)
96 pconnect = "PPP";
97 else if (bundle_Phase(p->bundle) == PHASE_NETWORK)
98 pconnect = "PPp";
99 else if (bundle_Phase(p->bundle) == PHASE_AUTHENTICATE)
100 pconnect = "Ppp";
101 else
102 pconnect = "ppp";
103
104 if (*shostname == '\0') {
105 char *p;
106
107 if (gethostname(shostname, sizeof shostname))
108 strcpy(shostname, "localhost");
109 else if ((p = strchr(shostname, '.')))
110 *p = '\0';
111 }
112
113 fprintf(p->Term, "%s%s%s> ", pconnect, pauth, shostname);
114 fflush(p->Term);
115}
116
73static int
74prompt_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
75{
76 struct prompt *p = descriptor2prompt(d);
77 int sets;
78
79 sets = 0;
80 if (p->fd_in >= 0) {

--- 4 unchanged lines hidden (view full) ---

85 if (e) {
86 FD_SET(p->fd_in, e);
87 sets++;
88 }
89 if (sets && *n < p->fd_in + 1)
90 *n = p->fd_in + 1;
91 }
92
117static int
118prompt_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
119{
120 struct prompt *p = descriptor2prompt(d);
121 int sets;
122
123 sets = 0;
124 if (p->fd_in >= 0) {

--- 4 unchanged lines hidden (view full) ---

129 if (e) {
130 FD_SET(p->fd_in, e);
131 sets++;
132 }
133 if (sets && *n < p->fd_in + 1)
134 *n = p->fd_in + 1;
135 }
136
137 prompt_Display(p);
138
93 return sets;
94}
95
96static int
97prompt_IsSet(struct descriptor *d, const fd_set *fdset)
98{
99 struct prompt *p = descriptor2prompt(d);
100 return p->fd_in >= 0 && FD_ISSET(p->fd_in, fdset);

--- 27 unchanged lines hidden (view full) ---

128
129 if (p->TermMode == NULL) {
130 n = read(p->fd_in, linebuff, sizeof linebuff - 1);
131 if (n > 0) {
132 if (linebuff[n-1] == '\n')
133 linebuff[--n] = '\0';
134 else
135 linebuff[n] = '\0';
139 return sets;
140}
141
142static int
143prompt_IsSet(struct descriptor *d, const fd_set *fdset)
144{
145 struct prompt *p = descriptor2prompt(d);
146 return p->fd_in >= 0 && FD_ISSET(p->fd_in, fdset);

--- 27 unchanged lines hidden (view full) ---

174
175 if (p->TermMode == NULL) {
176 n = read(p->fd_in, linebuff, sizeof linebuff - 1);
177 if (n > 0) {
178 if (linebuff[n-1] == '\n')
179 linebuff[--n] = '\0';
180 else
181 linebuff[n] = '\0';
136 prompt_nonewline = 1; /* In case DecodeCommand does a prompt */
182 p->nonewline = 1; /* Maybe DecodeCommand does a prompt */
183 prompt_Required(p);
137 if (n)
184 if (n)
138 DecodeCommand(bundle, linebuff, n, IsInteractive(0) ? NULL : "Client");
139 prompt_Display(&prompt, bundle);
185 DecodeCommand(bundle, linebuff, n, p,
186 IsInteractive(NULL) ? NULL : "Client");
140 } else if (n <= 0) {
141 LogPrintf(LogPHASE, "Client connection closed.\n");
187 } else if (n <= 0) {
188 LogPrintf(LogPHASE, "Client connection closed.\n");
142 prompt_Drop(&prompt, 0);
189 prompt_Destroy(p, 0);
143 }
144 return;
145 }
146
147 switch (p->TermMode->state) {
148 case DATALINK_CLOSED:
149 prompt_Printf(p, "Link lost, terminal mode.\n");
190 }
191 return;
192 }
193
194 switch (p->TermMode->state) {
195 case DATALINK_CLOSED:
196 prompt_Printf(p, "Link lost, terminal mode.\n");
150 prompt_TtyCommandMode(&prompt);
151 prompt_nonewline = 0;
152 prompt_Display(&prompt, bundle);
197 prompt_TtyCommandMode(p);
198 p->nonewline = 0;
199 prompt_Required(p);
153 return;
154
155 case DATALINK_READY:
156 break;
157
158 case DATALINK_OPEN:
159 prompt_Printf(p, "\nPacket mode detected.\n");
200 return;
201
202 case DATALINK_READY:
203 break;
204
205 case DATALINK_OPEN:
206 prompt_Printf(p, "\nPacket mode detected.\n");
160 prompt_TtyCommandMode(&prompt);
161 prompt_nonewline = 0;
207 prompt_TtyCommandMode(p);
208 p->nonewline = 0;
162 /* We'll get a prompt because of our status change */
163 /* Fall through */
164
165 default:
166 /* Wait 'till we're in a state we care about */
167 return;
168 }
169

--- 15 unchanged lines hidden (view full) ---

185 case 1:
186 switch (ch) {
187 case '?':
188 prompt_ShowHelp(p);
189 break;
190 case 'p':
191 datalink_Up(p->TermMode, 0, 1);
192 prompt_Printf(p, "\nPacket mode.\n");
209 /* We'll get a prompt because of our status change */
210 /* Fall through */
211
212 default:
213 /* Wait 'till we're in a state we care about */
214 return;
215 }
216

--- 15 unchanged lines hidden (view full) ---

232 case 1:
233 switch (ch) {
234 case '?':
235 prompt_ShowHelp(p);
236 break;
237 case 'p':
238 datalink_Up(p->TermMode, 0, 1);
239 prompt_Printf(p, "\nPacket mode.\n");
193 prompt_TtyCommandMode(&prompt);
240 prompt_TtyCommandMode(p);
194 break;
195 case '.':
241 break;
242 case '.':
196 prompt_TtyCommandMode(&prompt);
197 prompt_nonewline = 0;
198 prompt_Display(&prompt, bundle);
243 prompt_TtyCommandMode(p);
244 p->nonewline = 0;
245 prompt_Required(p);
199 break;
200 case 't':
246 break;
247 case 't':
201 ShowTimers(0);
248 ShowTimers(0, p);
202 break;
203 case 'm':
204 ShowMemMap(NULL);
205 break;
206 default:
207 if (Physical_Write(bundle2physical(bundle, NULL), &ch, n) < 0)
208 LogPrintf(LogERROR, "error writing to modem.\n");
209 break;

--- 6 unchanged lines hidden (view full) ---

216
217static void
218prompt_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
219{
220 /* We never want to write here ! */
221 LogPrintf(LogERROR, "prompt_Write: Internal error: Bad call !\n");
222}
223
249 break;
250 case 'm':
251 ShowMemMap(NULL);
252 break;
253 default:
254 if (Physical_Write(bundle2physical(bundle, NULL), &ch, n) < 0)
255 LogPrintf(LogERROR, "error writing to modem.\n");
256 break;

--- 6 unchanged lines hidden (view full) ---

263
264static void
265prompt_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
266{
267 /* We never want to write here ! */
268 LogPrintf(LogERROR, "prompt_Write: Internal error: Bad call !\n");
269}
270
224struct prompt prompt = {
225 {
226 PROMPT_DESCRIPTOR,
227 NULL,
228 prompt_UpdateSet,
229 prompt_IsSet,
230 prompt_Read,
231 prompt_Write
232 },
233 -1,
234 -1,
235 NULL
236};
237
238int
239prompt_Init(struct prompt *p, int fd)
271struct prompt *
272prompt_Create(struct server *s, struct bundle *bundle, int fd)
240{
273{
241 if (p->Term && p->Term != stdout)
242 return 0; /* must prompt_Drop() first */
274 struct prompt *p = (struct prompt *)malloc(sizeof(struct prompt));
243
275
244 if (fd == PROMPT_NONE) {
245 p->fd_in = p->fd_out = -1;
246 p->Term = NULL;
247 } else if (fd == PROMPT_STD) {
248 p->fd_in = STDIN_FILENO;
249 p->fd_out = STDOUT_FILENO;
250 p->Term = stdout;
251 } else {
252 p->fd_in = p->fd_out = fd;
253 p->Term = fdopen(fd, "a+");
276 if (p != NULL) {
277 p->desc.type = PROMPT_DESCRIPTOR;
278 p->desc.next = NULL;
279 p->desc.UpdateSet = prompt_UpdateSet;
280 p->desc.IsSet = prompt_IsSet;
281 p->desc.Read = prompt_Read;
282 p->desc.Write = prompt_Write;
283
284 if (fd == PROMPT_STD) {
285 p->fd_in = STDIN_FILENO;
286 p->fd_out = STDOUT_FILENO;
287 p->Term = stdout;
288 p->owner = NULL;
289 p->auth = LOCAL_AUTH;
290 snprintf(p->who, sizeof p->who, "Controller (%s)", ttyname(p->fd_out));
291 tcgetattr(p->fd_in, &p->oldtio); /* Save original tty mode */
292 } else {
293 p->fd_in = p->fd_out = fd;
294 p->Term = fdopen(fd, "a+");
295 p->owner = s;
296 p->auth = *s->passwd ? LOCAL_NO_AUTH : LOCAL_AUTH;
297 *p->who = '\0';
298 }
299 p->TermMode = NULL;
300 p->nonewline = 1;
301 p->needprompt = 1;
302 p->bundle = bundle;
303 if (p->bundle)
304 bundle_RegisterDescriptor(p->bundle, &p->desc);
305 log_RegisterPrompt(p);
254 }
306 }
255 p->TermMode = NULL;
256 tcgetattr(STDIN_FILENO, &p->oldtio); /* Save original tty mode */
257
307
258 return 1;
308 return p;
259}
260
261void
309}
310
311void
262prompt_Display(struct prompt *p, struct bundle *bundle)
312prompt_DestroyUnclean(struct prompt *p)
263{
313{
264 const char *pconnect, *pauth;
265
266 if (!p->Term || p->TermMode != NULL)
267 return;
268
269 if (prompt_nonewline)
270 prompt_nonewline = 0;
271 else
272 fprintf(p->Term, "\n");
273
274 if (VarLocalAuth == LOCAL_AUTH)
275 pauth = " ON ";
276 else
277 pauth = " on ";
278
279 if (bundle->ncp.ipcp.fsm.state == ST_OPENED)
280 pconnect = "PPP";
281 else if (bundle_Phase(bundle) == PHASE_NETWORK)
282 pconnect = "PPp";
283 else if (bundle_Phase(bundle) == PHASE_AUTHENTICATE)
284 pconnect = "Ppp";
285 else
286 pconnect = "ppp";
287
288 fprintf(p->Term, "%s%s%s> ", pconnect, pauth, VarShortHost);
289 fflush(p->Term);
314 log_UnRegisterPrompt(p);
315 bundle_UnRegisterDescriptor(p->bundle, &p->desc);
316 free(p);
290}
291
292void
317}
318
319void
293prompt_Drop(struct prompt *p, int verbose)
320prompt_Destroy(struct prompt *p, int verbose)
294{
321{
295 if (p->Term && p->Term != stdout) {
296 FILE *oVarTerm;
297
298 oVarTerm = p->Term;
299 p->Term = NULL;
300 if (oVarTerm)
301 fclose(oVarTerm);
322 if (p->Term != stdout) {
323 fclose(p->Term);
302 close(p->fd_in);
303 if (p->fd_out != p->fd_in)
304 close(p->fd_out);
324 close(p->fd_in);
325 if (p->fd_out != p->fd_in)
326 close(p->fd_out);
305 p->fd_in = p->fd_out = -1;
306 if (verbose)
307 LogPrintf(LogPHASE, "Client connection dropped.\n");
327 if (verbose)
328 LogPrintf(LogPHASE, "Client connection dropped.\n");
308 }
329 } else
330 prompt_TtyOldMode(p);
331
332 prompt_DestroyUnclean(p);
309}
310
311void
312prompt_Printf(struct prompt *p, const char *fmt,...)
313{
333}
334
335void
336prompt_Printf(struct prompt *p, const char *fmt,...)
337{
314 if (p->Term) {
338 if (p) {
315 va_list ap;
316
317 va_start(ap, fmt);
318 vfprintf(p->Term, fmt, ap);
319 fflush(p->Term);
320 va_end(ap);
321 }
322}
323
324void
325prompt_vPrintf(struct prompt *p, const char *fmt, va_list ap)
326{
339 va_list ap;
340
341 va_start(ap, fmt);
342 vfprintf(p->Term, fmt, ap);
343 fflush(p->Term);
344 va_end(ap);
345 }
346}
347
348void
349prompt_vPrintf(struct prompt *p, const char *fmt, va_list ap)
350{
327 if (p->Term) {
351 if (p) {
328 vfprintf(p->Term, fmt, ap);
329 fflush(p->Term);
330 }
331}
332
333void
334prompt_TtyInit(struct prompt *p, int DontWantInt)
335{
352 vfprintf(p->Term, fmt, ap);
353 fflush(p->Term);
354 }
355}
356
357void
358prompt_TtyInit(struct prompt *p, int DontWantInt)
359{
336 struct termios newtio;
337 int stat;
338
339 stat = fcntl(p->fd_in, F_GETFL, 0);
340 if (stat > 0) {
341 stat |= O_NONBLOCK;
360 int stat;
361
362 stat = fcntl(p->fd_in, F_GETFL, 0);
363 if (stat > 0) {
364 stat |= O_NONBLOCK;
342 (void) fcntl(p->fd_in, F_SETFL, stat);
365 fcntl(p->fd_in, F_SETFL, stat);
343 }
366 }
344 newtio = p->oldtio;
345 newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
346 newtio.c_iflag = 0;
347 newtio.c_oflag &= ~OPOST;
348 newtio.c_cc[VEOF] = _POSIX_VDISABLE;
349 if (DontWantInt)
350 newtio.c_cc[VINTR] = _POSIX_VDISABLE;
351 newtio.c_cc[VMIN] = 1;
352 newtio.c_cc[VTIME] = 0;
353 newtio.c_cflag |= CS8;
354 tcsetattr(p->fd_in, TCSANOW, &newtio);
355 p->comtio = newtio;
367
368 if (p->Term == stdout) {
369 struct termios newtio;
370
371 newtio = p->oldtio;
372 newtio.c_lflag &= ~(ECHO | ISIG | ICANON);
373 newtio.c_iflag = 0;
374 newtio.c_oflag &= ~OPOST;
375 newtio.c_cc[VEOF] = _POSIX_VDISABLE;
376 if (DontWantInt)
377 newtio.c_cc[VINTR] = _POSIX_VDISABLE;
378 newtio.c_cc[VMIN] = 1;
379 newtio.c_cc[VTIME] = 0;
380 newtio.c_cflag |= CS8;
381 tcsetattr(p->fd_in, TCSANOW, &newtio);
382 p->comtio = newtio;
383 }
356}
357
358/*
359 * Set tty into command mode. We allow canonical input and echo processing.
360 */
361void
362prompt_TtyCommandMode(struct prompt *p)
363{
364 struct termios newtio;
365 int stat;
366
384}
385
386/*
387 * Set tty into command mode. We allow canonical input and echo processing.
388 */
389void
390prompt_TtyCommandMode(struct prompt *p)
391{
392 struct termios newtio;
393 int stat;
394
367 if (!(mode & MODE_INTER))
368 return;
369
370 tcgetattr(p->fd_in, &newtio);
371 newtio.c_lflag |= (ECHO | ISIG | ICANON);
372 newtio.c_iflag = p->oldtio.c_iflag;
373 newtio.c_oflag |= OPOST;
374 tcsetattr(p->fd_in, TCSADRAIN, &newtio);
395 tcgetattr(p->fd_in, &newtio);
396 newtio.c_lflag |= (ECHO | ISIG | ICANON);
397 newtio.c_iflag = p->oldtio.c_iflag;
398 newtio.c_oflag |= OPOST;
399 tcsetattr(p->fd_in, TCSADRAIN, &newtio);
400
375 stat = fcntl(p->fd_in, F_GETFL, 0);
376 if (stat > 0) {
377 stat |= O_NONBLOCK;
401 stat = fcntl(p->fd_in, F_GETFL, 0);
402 if (stat > 0) {
403 stat |= O_NONBLOCK;
378 (void) fcntl(p->fd_in, F_SETFL, stat);
404 fcntl(p->fd_in, F_SETFL, stat);
379 }
405 }
406
380 p->TermMode = NULL;
381}
382
383/*
384 * Set tty into terminal mode which is used while we invoke term command.
385 */
386void
387prompt_TtyTermMode(struct prompt *p, struct datalink *dl)
388{
389 int stat;
390
407 p->TermMode = NULL;
408}
409
410/*
411 * Set tty into terminal mode which is used while we invoke term command.
412 */
413void
414prompt_TtyTermMode(struct prompt *p, struct datalink *dl)
415{
416 int stat;
417
391 tcsetattr(p->fd_in, TCSADRAIN, &p->comtio);
418 prompt_Printf(p, "Entering terminal mode on %s.\n", dl->name);
419 prompt_Printf(p, "Type `~?' for help.\n");
420
421 if (p->Term == stdout)
422 tcsetattr(p->fd_in, TCSADRAIN, &p->comtio);
423
392 stat = fcntl(p->fd_in, F_GETFL, 0);
393 if (stat > 0) {
394 stat &= ~O_NONBLOCK;
424 stat = fcntl(p->fd_in, F_GETFL, 0);
425 if (stat > 0) {
426 stat &= ~O_NONBLOCK;
395 (void) fcntl(p->fd_in, F_SETFL, stat);
427 fcntl(p->fd_in, F_SETFL, stat);
396 }
397 p->TermMode = dl;
398}
399
400void
401prompt_TtyOldMode(struct prompt *p)
402{
403 int stat;
404
405 stat = fcntl(p->fd_in, F_GETFL, 0);
406 if (stat > 0) {
407 stat &= ~O_NONBLOCK;
428 }
429 p->TermMode = dl;
430}
431
432void
433prompt_TtyOldMode(struct prompt *p)
434{
435 int stat;
436
437 stat = fcntl(p->fd_in, F_GETFL, 0);
438 if (stat > 0) {
439 stat &= ~O_NONBLOCK;
408 (void) fcntl(p->fd_in, F_SETFL, stat);
440 fcntl(p->fd_in, F_SETFL, stat);
409 }
441 }
410 tcsetattr(p->fd_in, TCSADRAIN, &p->oldtio);
442
443 if (p->Term == stdout)
444 tcsetattr(p->fd_in, TCSADRAIN, &p->oldtio);
411}
412
413pid_t
414prompt_pgrp(struct prompt *p)
415{
445}
446
447pid_t
448prompt_pgrp(struct prompt *p)
449{
416 return p->Term ? tcgetpgrp(p->fd_in) : -1;
450 return tcgetpgrp(p->fd_in);
417}
451}
452
453int
454PasswdCommand(struct cmdargs const *arg)
455{
456 const char *pass;
457
458 if (!arg->prompt) {
459 LogPrintf(LogWARN, "passwd: Cannot specify without a prompt\n");
460 return 0;
461 }
462
463 if (arg->prompt->owner == NULL) {
464 LogPrintf(LogWARN, "passwd: Not required\n");
465 return 0;
466 }
467
468 if (arg->argc == 0)
469 pass = "";
470 else if (arg->argc > 1)
471 return -1;
472 else
473 pass = *arg->argv;
474
475 if (!strcmp(arg->prompt->owner->passwd, pass))
476 arg->prompt->auth = LOCAL_AUTH;
477 else
478 arg->prompt->auth = LOCAL_NO_AUTH;
479
480 return 0;
481}