prompt.c revision 43313
136285Sbrian/*- 236285Sbrian * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org> 336285Sbrian * All rights reserved. 436285Sbrian * 536285Sbrian * Redistribution and use in source and binary forms, with or without 636285Sbrian * modification, are permitted provided that the following conditions 736285Sbrian * are met: 836285Sbrian * 1. Redistributions of source code must retain the above copyright 936285Sbrian * notice, this list of conditions and the following disclaimer. 1036285Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1136285Sbrian * notice, this list of conditions and the following disclaimer in the 1236285Sbrian * documentation and/or other materials provided with the distribution. 1336285Sbrian * 1436285Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1536285Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1636285Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1736285Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1836285Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1936285Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2036285Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2136285Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2236285Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2336285Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2436285Sbrian * SUCH DAMAGE. 2536285Sbrian * 2643313Sbrian * $Id: prompt.c,v 1.12 1998/08/26 17:39:37 brian Exp $ 2736285Sbrian */ 2836285Sbrian 2936285Sbrian#include <sys/param.h> 3036285Sbrian#include <netinet/in.h> 3136285Sbrian#include <netinet/in_systm.h> 3236285Sbrian#include <netinet/ip.h> 3336285Sbrian#include <sys/un.h> 3436285Sbrian 3536285Sbrian#include <errno.h> 3636285Sbrian#include <stdarg.h> 3736285Sbrian#include <stdio.h> 3836285Sbrian#include <stdlib.h> 3936285Sbrian#include <string.h> 4036285Sbrian#include <sys/fcntl.h> 4136285Sbrian#include <termios.h> 4236285Sbrian#include <unistd.h> 4336285Sbrian 4436285Sbrian#include "defs.h" 4536285Sbrian#include "timer.h" 4636285Sbrian#include "command.h" 4736285Sbrian#include "log.h" 4836285Sbrian#include "descriptor.h" 4936285Sbrian#include "prompt.h" 5036285Sbrian#include "fsm.h" 5136285Sbrian#include "lcp.h" 5236285Sbrian#include "auth.h" 5336285Sbrian#include "iplist.h" 5436285Sbrian#include "throughput.h" 5536285Sbrian#include "slcompress.h" 5638557Sbrian#include "mbuf.h" 5738557Sbrian#include "lqr.h" 5838557Sbrian#include "hdlc.h" 5936285Sbrian#include "ipcp.h" 6036285Sbrian#include "filter.h" 6136285Sbrian#include "async.h" 6236285Sbrian#include "ccp.h" 6336285Sbrian#include "link.h" 6436285Sbrian#include "physical.h" 6536285Sbrian#include "mp.h" 6643313Sbrian#ifndef NORADIUS 6743313Sbrian#include "radius.h" 6843313Sbrian#endif 6936285Sbrian#include "bundle.h" 7036285Sbrian#include "chat.h" 7136285Sbrian#include "chap.h" 7238174Sbrian#include "cbcp.h" 7336285Sbrian#include "datalink.h" 7436285Sbrian#include "server.h" 7537386Sbrian#include "main.h" 7636285Sbrian 7736285Sbrianstatic void 7836285Sbrianprompt_Display(struct prompt *p) 7936285Sbrian{ 8037010Sbrian /* XXX: See Index2Nam() - should we only figure this out once ? */ 8136285Sbrian static char shostname[MAXHOSTNAMELEN]; 8236285Sbrian const char *pconnect, *pauth; 8336285Sbrian 8436285Sbrian if (p->TermMode || !p->needprompt) 8536285Sbrian return; 8636285Sbrian 8736285Sbrian p->needprompt = 0; 8836285Sbrian 8936285Sbrian if (p->nonewline) 9036285Sbrian p->nonewline = 0; 9136285Sbrian else 9236285Sbrian fprintf(p->Term, "\n"); 9336285Sbrian 9436285Sbrian if (p->auth == LOCAL_AUTH) 9536285Sbrian pauth = " ON "; 9636285Sbrian else 9736285Sbrian pauth = " on "; 9836285Sbrian 9936285Sbrian if (p->bundle->ncp.ipcp.fsm.state == ST_OPENED) 10036285Sbrian pconnect = "PPP"; 10136285Sbrian else if (bundle_Phase(p->bundle) == PHASE_NETWORK) 10236285Sbrian pconnect = "PPp"; 10336285Sbrian else if (bundle_Phase(p->bundle) == PHASE_AUTHENTICATE) 10436285Sbrian pconnect = "Ppp"; 10536285Sbrian else 10636285Sbrian pconnect = "ppp"; 10736285Sbrian 10836285Sbrian if (*shostname == '\0') { 10936285Sbrian char *dot; 11036285Sbrian 11136285Sbrian if (gethostname(shostname, sizeof shostname)) 11236285Sbrian strcpy(shostname, "localhost"); 11336285Sbrian else if ((dot = strchr(shostname, '.'))) 11436285Sbrian *dot = '\0'; 11536285Sbrian } 11636285Sbrian 11736285Sbrian fprintf(p->Term, "%s%s%s> ", pconnect, pauth, shostname); 11836285Sbrian fflush(p->Term); 11936285Sbrian} 12036285Sbrian 12136285Sbrianstatic int 12236285Sbrianprompt_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 12336285Sbrian{ 12436285Sbrian struct prompt *p = descriptor2prompt(d); 12536285Sbrian int sets; 12636285Sbrian 12736285Sbrian sets = 0; 12836285Sbrian 12936285Sbrian if (!p->active) 13036285Sbrian return sets; 13136285Sbrian 13236285Sbrian if (p->fd_in >= 0) { 13336285Sbrian if (r) { 13436285Sbrian FD_SET(p->fd_in, r); 13536285Sbrian log_Printf(LogTIMER, "prompt %s: fdset(r) %d\n", p->src.from, p->fd_in); 13636285Sbrian sets++; 13736285Sbrian } 13836285Sbrian if (e) { 13936285Sbrian FD_SET(p->fd_in, e); 14036285Sbrian log_Printf(LogTIMER, "prompt %s: fdset(e) %d\n", p->src.from, p->fd_in); 14136285Sbrian sets++; 14236285Sbrian } 14336285Sbrian if (sets && *n < p->fd_in + 1) 14436285Sbrian *n = p->fd_in + 1; 14536285Sbrian } 14636285Sbrian 14736285Sbrian prompt_Display(p); 14836285Sbrian 14936285Sbrian return sets; 15036285Sbrian} 15136285Sbrian 15236285Sbrianstatic int 15336285Sbrianprompt_IsSet(struct descriptor *d, const fd_set *fdset) 15436285Sbrian{ 15536285Sbrian struct prompt *p = descriptor2prompt(d); 15636285Sbrian return p->fd_in >= 0 && FD_ISSET(p->fd_in, fdset); 15736285Sbrian} 15836285Sbrian 15936285Sbrian 16036285Sbrianstatic void 16136285Sbrianprompt_ShowHelp(struct prompt *p) 16236285Sbrian{ 16337011Sbrian prompt_Printf(p, "The following commands are available:\n"); 16437011Sbrian prompt_Printf(p, " ~p\tEnter Packet mode\n"); 16537011Sbrian prompt_Printf(p, " ~t\tShow timers\n"); 16637011Sbrian prompt_Printf(p, " ~m\tShow memory map\n"); 16737011Sbrian prompt_Printf(p, " ~.\tTerminate program\n"); 16837011Sbrian prompt_Printf(p, " ~?\tThis help\n"); 16936285Sbrian} 17036285Sbrian 17136285Sbrianstatic void 17236285Sbrianprompt_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 17336285Sbrian{ 17436285Sbrian struct prompt *p = descriptor2prompt(d); 17536285Sbrian int n; 17636285Sbrian char ch; 17736285Sbrian char linebuff[LINE_LEN]; 17836285Sbrian 17936285Sbrian if (p->TermMode == NULL) { 18036285Sbrian n = read(p->fd_in, linebuff, sizeof linebuff - 1); 18136285Sbrian if (n > 0) { 18236285Sbrian if (linebuff[n-1] == '\n') 18336285Sbrian linebuff[--n] = '\0'; 18436285Sbrian else 18536285Sbrian linebuff[n] = '\0'; 18636285Sbrian p->nonewline = 1; /* Maybe command_Decode does a prompt */ 18736285Sbrian prompt_Required(p); 18836285Sbrian if (n) 18936285Sbrian command_Decode(bundle, linebuff, n, p, p->src.from); 19036285Sbrian } else if (n <= 0) { 19136314Sbrian log_Printf(LogPHASE, "%s: Client connection closed.\n", p->src.from); 19237386Sbrian if (!p->owner) 19337386Sbrian Cleanup(EX_NORMAL); 19436285Sbrian prompt_Destroy(p, 0); 19536285Sbrian } 19636285Sbrian return; 19736285Sbrian } 19836285Sbrian 19936285Sbrian switch (p->TermMode->state) { 20036285Sbrian case DATALINK_CLOSED: 20136285Sbrian prompt_Printf(p, "Link lost, terminal mode.\n"); 20236285Sbrian prompt_TtyCommandMode(p); 20336285Sbrian p->nonewline = 0; 20436285Sbrian prompt_Required(p); 20536285Sbrian return; 20636285Sbrian 20736285Sbrian case DATALINK_READY: 20836285Sbrian break; 20936285Sbrian 21036285Sbrian case DATALINK_OPEN: 21136285Sbrian prompt_Printf(p, "\nPacket mode detected.\n"); 21236285Sbrian prompt_TtyCommandMode(p); 21336285Sbrian p->nonewline = 0; 21436285Sbrian /* We'll get a prompt because of our status change */ 21536285Sbrian /* Fall through */ 21636285Sbrian 21736285Sbrian default: 21836285Sbrian /* Wait 'till we're in a state we care about */ 21936285Sbrian return; 22036285Sbrian } 22136285Sbrian 22236285Sbrian /* 22336285Sbrian * We are in terminal mode, decode special sequences 22436285Sbrian */ 22536285Sbrian n = read(p->fd_in, &ch, 1); 22636285Sbrian log_Printf(LogDEBUG, "Got %d bytes (reading from the terminal)\n", n); 22736285Sbrian 22836285Sbrian if (n > 0) { 22937010Sbrian switch (p->readtilde) { 23036285Sbrian case 0: 23136285Sbrian if (ch == '~') 23237010Sbrian p->readtilde = 1; 23336285Sbrian else 23436285Sbrian if (physical_Write(p->TermMode->physical, &ch, n) < 0) { 23537019Sbrian log_Printf(LogWARN, "error writing to modem: %s\n", strerror(errno)); 23636285Sbrian prompt_TtyCommandMode(p); 23736285Sbrian } 23836285Sbrian break; 23936285Sbrian case 1: 24036285Sbrian switch (ch) { 24136285Sbrian case '?': 24236285Sbrian prompt_ShowHelp(p); 24336285Sbrian break; 24436285Sbrian case 'p': 24536285Sbrian datalink_Up(p->TermMode, 0, 1); 24636285Sbrian prompt_Printf(p, "\nPacket mode.\n"); 24736285Sbrian prompt_TtyCommandMode(p); 24836285Sbrian break; 24936285Sbrian case '.': 25036285Sbrian prompt_TtyCommandMode(p); 25136285Sbrian p->nonewline = 0; 25236285Sbrian prompt_Required(p); 25336285Sbrian break; 25436285Sbrian case 't': 25536285Sbrian timer_Show(0, p); 25636285Sbrian break; 25736285Sbrian case 'm': 25837011Sbrian { 25937011Sbrian struct cmdargs arg; 26037011Sbrian 26137011Sbrian arg.cmdtab = NULL; 26237011Sbrian arg.cmd = NULL; 26337011Sbrian arg.argc = 0; 26437011Sbrian arg.argn = 0; 26537011Sbrian arg.argv = NULL; 26637011Sbrian arg.bundle = bundle; 26737011Sbrian arg.cx = p->TermMode; 26837011Sbrian arg.prompt = p; 26937011Sbrian 27037011Sbrian mbuf_Show(&arg); 27137011Sbrian } 27236285Sbrian break; 27336285Sbrian default: 27436285Sbrian if (physical_Write(p->TermMode->physical, &ch, n) < 0) { 27537019Sbrian log_Printf(LogWARN, "error writing to modem: %s\n", strerror(errno)); 27636285Sbrian prompt_TtyCommandMode(p); 27736285Sbrian } 27836285Sbrian break; 27936285Sbrian } 28037010Sbrian p->readtilde = 0; 28136285Sbrian break; 28236285Sbrian } 28336285Sbrian } 28436285Sbrian} 28536285Sbrian 28637141Sbrianstatic int 28736285Sbrianprompt_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 28836285Sbrian{ 28936285Sbrian /* We never want to write here ! */ 29037019Sbrian log_Printf(LogALERT, "prompt_Write: Internal error: Bad call !\n"); 29137141Sbrian return 0; 29236285Sbrian} 29336285Sbrian 29436285Sbrianstruct prompt * 29536285Sbrianprompt_Create(struct server *s, struct bundle *bundle, int fd) 29636285Sbrian{ 29736285Sbrian struct prompt *p = (struct prompt *)malloc(sizeof(struct prompt)); 29836285Sbrian 29936285Sbrian if (p != NULL) { 30036285Sbrian p->desc.type = PROMPT_DESCRIPTOR; 30136285Sbrian p->desc.UpdateSet = prompt_UpdateSet; 30236285Sbrian p->desc.IsSet = prompt_IsSet; 30336285Sbrian p->desc.Read = prompt_Read; 30436285Sbrian p->desc.Write = prompt_Write; 30536285Sbrian 30636285Sbrian if (fd == PROMPT_STD) { 30736431Sbrian char *tty = ttyname(STDIN_FILENO); 30836431Sbrian 30936431Sbrian if (!tty) { 31036431Sbrian free(p); 31136431Sbrian return NULL; 31236431Sbrian } 31336285Sbrian p->fd_in = STDIN_FILENO; 31436285Sbrian p->fd_out = STDOUT_FILENO; 31536285Sbrian p->Term = stdout; 31636285Sbrian p->owner = NULL; 31736285Sbrian p->auth = LOCAL_AUTH; 31836285Sbrian p->src.type = "Controller"; 31936431Sbrian strncpy(p->src.from, tty, sizeof p->src.from - 1); 32036285Sbrian p->src.from[sizeof p->src.from - 1] = '\0'; 32136285Sbrian tcgetattr(p->fd_in, &p->oldtio); /* Save original tty mode */ 32236285Sbrian } else { 32336285Sbrian p->fd_in = p->fd_out = fd; 32436285Sbrian p->Term = fdopen(fd, "a+"); 32536285Sbrian p->owner = s; 32636285Sbrian p->auth = *s->passwd ? LOCAL_NO_AUTH : LOCAL_AUTH; 32736285Sbrian p->src.type = "unknown"; 32836285Sbrian *p->src.from = '\0'; 32936285Sbrian } 33036285Sbrian p->TermMode = NULL; 33136285Sbrian p->nonewline = 1; 33236285Sbrian p->needprompt = 1; 33337010Sbrian p->readtilde = 0; 33436285Sbrian p->bundle = bundle; 33536285Sbrian log_RegisterPrompt(p); 33636285Sbrian } 33736285Sbrian 33836285Sbrian return p; 33936285Sbrian} 34036285Sbrian 34136285Sbrianvoid 34236285Sbrianprompt_Destroy(struct prompt *p, int verbose) 34336285Sbrian{ 34436431Sbrian if (p) { 34536431Sbrian if (p->Term != stdout) { 34636431Sbrian fclose(p->Term); 34736431Sbrian close(p->fd_in); 34836431Sbrian if (p->fd_out != p->fd_in) 34936431Sbrian close(p->fd_out); 35036431Sbrian if (verbose) 35136431Sbrian log_Printf(LogPHASE, "%s: Client connection dropped.\n", p->src.from); 35236431Sbrian } else 35336431Sbrian prompt_TtyOldMode(p); 35436285Sbrian 35536431Sbrian log_UnRegisterPrompt(p); 35636431Sbrian free(p); 35736431Sbrian } 35836285Sbrian} 35936285Sbrian 36036285Sbrianvoid 36136285Sbrianprompt_Printf(struct prompt *p, const char *fmt,...) 36236285Sbrian{ 36336285Sbrian if (p && p->active) { 36436285Sbrian va_list ap; 36537011Sbrian 36636285Sbrian va_start(ap, fmt); 36737011Sbrian prompt_vPrintf(p, fmt, ap); 36836285Sbrian va_end(ap); 36936285Sbrian } 37036285Sbrian} 37136285Sbrian 37236285Sbrianvoid 37336285Sbrianprompt_vPrintf(struct prompt *p, const char *fmt, va_list ap) 37436285Sbrian{ 37536285Sbrian if (p && p->active) { 37637011Sbrian char nfmt[LINE_LEN]; 37737011Sbrian const char *pfmt; 37837011Sbrian 37937011Sbrian if (p->TermMode) { 38037011Sbrian /* Stuff '\r' in front of '\n' 'cos we're in raw mode */ 38137011Sbrian int len = strlen(fmt); 38237011Sbrian 38337011Sbrian if (len && len < sizeof nfmt - 1 && fmt[len-1] == '\n') { 38437011Sbrian strcpy(nfmt, fmt); 38537011Sbrian strcpy(nfmt + len - 1, "\r\n"); 38637011Sbrian pfmt = nfmt; 38737011Sbrian } else 38837011Sbrian pfmt = fmt; 38937011Sbrian } else 39037011Sbrian pfmt = fmt; 39137011Sbrian vfprintf(p->Term, pfmt, ap); 39236285Sbrian fflush(p->Term); 39336285Sbrian p->nonewline = 1; 39436285Sbrian } 39536285Sbrian} 39636285Sbrian 39736285Sbrianvoid 39836285Sbrianprompt_TtyInit(struct prompt *p) 39936285Sbrian{ 40036285Sbrian int stat, fd = p ? p->fd_in : STDIN_FILENO; 40136285Sbrian struct termios newtio; 40236285Sbrian 40336285Sbrian stat = fcntl(fd, F_GETFL, 0); 40436285Sbrian if (stat > 0) { 40536285Sbrian stat |= O_NONBLOCK; 40636285Sbrian fcntl(fd, F_SETFL, stat); 40736285Sbrian } 40836285Sbrian 40936285Sbrian if (p) 41036285Sbrian newtio = p->oldtio; 41136285Sbrian else 41236285Sbrian tcgetattr(fd, &newtio); 41336285Sbrian 41436285Sbrian newtio.c_lflag &= ~(ECHO | ISIG | ICANON); 41536285Sbrian newtio.c_iflag = 0; 41636285Sbrian newtio.c_oflag &= ~OPOST; 41736285Sbrian if (!p) 41836285Sbrian newtio.c_cc[VINTR] = _POSIX_VDISABLE; 41936285Sbrian newtio.c_cc[VMIN] = 1; 42036285Sbrian newtio.c_cc[VTIME] = 0; 42136285Sbrian newtio.c_cflag |= CS8; 42236285Sbrian tcsetattr(fd, TCSANOW, &newtio); 42336285Sbrian if (p) 42436285Sbrian p->comtio = newtio; 42536285Sbrian} 42636285Sbrian 42736285Sbrian/* 42836285Sbrian * Set tty into command mode. We allow canonical input and echo processing. 42936285Sbrian */ 43036285Sbrianvoid 43136285Sbrianprompt_TtyCommandMode(struct prompt *p) 43236285Sbrian{ 43336285Sbrian struct termios newtio; 43436285Sbrian int stat; 43536285Sbrian 43636285Sbrian tcgetattr(p->fd_in, &newtio); 43736285Sbrian newtio.c_lflag |= (ECHO | ISIG | ICANON); 43836285Sbrian newtio.c_iflag = p->oldtio.c_iflag; 43936285Sbrian newtio.c_oflag |= OPOST; 44036285Sbrian tcsetattr(p->fd_in, TCSADRAIN, &newtio); 44136285Sbrian 44236285Sbrian stat = fcntl(p->fd_in, F_GETFL, 0); 44336285Sbrian if (stat > 0) { 44436285Sbrian stat |= O_NONBLOCK; 44536285Sbrian fcntl(p->fd_in, F_SETFL, stat); 44636285Sbrian } 44736285Sbrian 44836285Sbrian p->TermMode = NULL; 44936285Sbrian} 45036285Sbrian 45136285Sbrian/* 45236285Sbrian * Set tty into terminal mode which is used while we invoke term command. 45336285Sbrian */ 45436285Sbrianvoid 45536285Sbrianprompt_TtyTermMode(struct prompt *p, struct datalink *dl) 45636285Sbrian{ 45736285Sbrian int stat; 45836285Sbrian 45936285Sbrian if (p->Term == stdout) 46036285Sbrian tcsetattr(p->fd_in, TCSADRAIN, &p->comtio); 46136285Sbrian 46236285Sbrian stat = fcntl(p->fd_in, F_GETFL, 0); 46336285Sbrian if (stat > 0) { 46436285Sbrian stat &= ~O_NONBLOCK; 46536285Sbrian fcntl(p->fd_in, F_SETFL, stat); 46636285Sbrian } 46736285Sbrian p->TermMode = dl; 46836285Sbrian} 46936285Sbrian 47036285Sbrianvoid 47136285Sbrianprompt_TtyOldMode(struct prompt *p) 47236285Sbrian{ 47336285Sbrian int stat; 47436285Sbrian 47536285Sbrian stat = fcntl(p->fd_in, F_GETFL, 0); 47636285Sbrian if (stat > 0) { 47736285Sbrian stat &= ~O_NONBLOCK; 47836285Sbrian fcntl(p->fd_in, F_SETFL, stat); 47936285Sbrian } 48036285Sbrian 48136285Sbrian if (p->Term == stdout) 48236285Sbrian tcsetattr(p->fd_in, TCSADRAIN, &p->oldtio); 48336285Sbrian} 48436285Sbrian 48536285Sbrianpid_t 48636285Sbrianprompt_pgrp(struct prompt *p) 48736285Sbrian{ 48836285Sbrian return tcgetpgrp(p->fd_in); 48936285Sbrian} 49036285Sbrian 49136285Sbrianint 49236285SbrianPasswdCommand(struct cmdargs const *arg) 49336285Sbrian{ 49436285Sbrian const char *pass; 49536285Sbrian 49636285Sbrian if (!arg->prompt) { 49736285Sbrian log_Printf(LogWARN, "passwd: Cannot specify without a prompt\n"); 49836285Sbrian return 0; 49936285Sbrian } 50036285Sbrian 50136285Sbrian if (arg->prompt->owner == NULL) { 50236285Sbrian log_Printf(LogWARN, "passwd: Not required\n"); 50336285Sbrian return 0; 50436285Sbrian } 50536285Sbrian 50636285Sbrian if (arg->argc == arg->argn) 50736285Sbrian pass = ""; 50836285Sbrian else if (arg->argc > arg->argn+1) 50936285Sbrian return -1; 51036285Sbrian else 51136285Sbrian pass = arg->argv[arg->argn]; 51236285Sbrian 51336285Sbrian if (!strcmp(arg->prompt->owner->passwd, pass)) 51436285Sbrian arg->prompt->auth = LOCAL_AUTH; 51536285Sbrian else 51636285Sbrian arg->prompt->auth = LOCAL_NO_AUTH; 51736285Sbrian 51836285Sbrian return 0; 51936285Sbrian} 52036285Sbrian 52136285Sbrianstatic struct pppTimer bgtimer; 52236285Sbrian 52336285Sbrianstatic void 52436285Sbrianprompt_TimedContinue(void *v) 52536285Sbrian{ 52636285Sbrian prompt_Continue((struct prompt *)v); 52736285Sbrian} 52836285Sbrian 52936285Sbrianvoid 53036285Sbrianprompt_Continue(struct prompt *p) 53136285Sbrian{ 53236285Sbrian timer_Stop(&bgtimer); 53336285Sbrian if (getpgrp() == prompt_pgrp(p)) { 53436285Sbrian prompt_TtyCommandMode(p); 53536285Sbrian p->nonewline = 1; 53636285Sbrian prompt_Required(p); 53736314Sbrian log_ActivatePrompt(p); 53836285Sbrian } else if (!p->owner) { 53936285Sbrian bgtimer.func = prompt_TimedContinue; 54036285Sbrian bgtimer.name = "prompt bg"; 54136285Sbrian bgtimer.load = SECTICKS; 54236285Sbrian bgtimer.arg = p; 54336285Sbrian timer_Start(&bgtimer); 54436285Sbrian } 54536285Sbrian} 54636285Sbrian 54736285Sbrianvoid 54836285Sbrianprompt_Suspend(struct prompt *p) 54936285Sbrian{ 55036285Sbrian if (getpgrp() == prompt_pgrp(p)) { 55136285Sbrian prompt_TtyOldMode(p); 55236314Sbrian log_DeactivatePrompt(p); 55336285Sbrian } 55436285Sbrian} 555