P8000/WEGA/contrib/K5JB/ttydriv.c

462 lines
9.6 KiB
C

/* Added redisplay of previous line with some limited line editing. Made
* changes to prevent array over-writes. Note that echo() and noecho()
* are only used by ftpcli.c during the password part of a login. Elim-
* inating them only reduced code size by 50 or so bytes. The editing
* costs 436 bytes and can be eliminated with an #undef EDIT.
* 3/18/92 - K5JB
*/
/* TTY input driver */
/* #define CUTE_FTP in config.h to enable FTP login prompting */
#include <stdio.h>
#include <ctype.h>
#include "options.h"
#include "config.h"
#include "global.h"
#include "mbuf.h"
#include "netuser.h"
#include "timer.h"
#ifdef AX25
#include "ax25.h"
#include "lapb.h"
#endif
#ifdef NETROM
#include "nr4.h"
#endif
#ifndef WEGA
#include "iface.h"
#endif
#include "tcp.h"
#include "session.h"
#include "cmdparse.h"
#include "telnet.h"
#include "ftp.h"
#ifdef _FINGER
#include "finger.h"
#endif
#ifdef UNIX
#include "unixopt.h"
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define EDIT
int ttymode,cmdmode(),go();
#define TTY_LIT 0 /* Send next char literally */
#define TTY_RAW 1
#define TTY_COOKED 2
#ifdef CUTE_FTP
int ttyecho=1;
#define TTY_NOECHO 0
#define TTY_ECHO 1
#endif
#ifdef CUTE_VIDEO
extern unsigned int saved_attrib;
void putca();
#endif
#ifdef FLOW
int ttyflow=1;
#endif
#define KBLINSIZ 80
#ifdef EDIT
#define CTLE 5 /* redisplay last line */
#define CTLF 6 /* cursor forward one word */
#define CTLD 4 /* cursor forward one char */
#define CTLS 19 /* cursor backward (non-destructive) */
#endif
#define CTLA 1 /* cursor back one word */
#define CTLR 18 /* redisplay current line */
#define CTLY 25 /* delete current line */
#define CTLU 21 /* ditto - backwards compat. */
#define CTLV 22
#define CTLW 23
#define CTLZ 26
#define RUBOUT 127
#ifdef SYS5
extern int background;
#ifdef USE_QUIT
extern int reportquit_flag;
void report_quit();
#endif
#ifdef FORKSHELL
extern int shellpid;
#endif
#endif
#if defined(UNIX)
extern char escape;
#endif
extern int mode;
int Keyhit = -1;
int noprompt; /* things to control prompts */
/* Process any keyboard input - removed from main() to make accessable
* by other processes - K5JB
*/
void
check_kbd()
{
char *ttybuf;
int c;
int16 cnt;
int ttydriv(),cmdparse(),kbread();
#ifdef FLOW
extern int ttyflow;
#endif
extern struct cmds cmds[];
extern char prompt[];
#ifdef SYS5
#ifdef USE_QUIT
if(reportquit_flag) /* set by quit signal and report is deferred */
report_quit(); /* until now */
#endif
/* note that if shellpid, kbread() always returns -1 */
while((background == 0) && ((c = kbread()) != -1))
#else
while((c = kbread()) != -1)
#endif
{
#ifdef MSDOS
/* c == -2 means the command escape key (F10) */
Keyhit = c; /* a global we use for haktc */
if(c == -2){
if(mode != CMD_MODE){
#ifdef CUTE_VIDEO
putca('\n',saved_attrib); /* in case we were in session */
#else
printf("\n");
#endif
cmdmode();
}
continue;
}
#endif
#if defined(UNIX) || defined(_OSK)
if(c == escape && escape != 0){
if(mode != CMD_MODE){
printf("\n");
cmdmode();
}
continue;
}
#endif /* UNIX or _OSK */
#ifndef FLOW
if ((cnt = ttydriv(c, &ttybuf)) == 0)
continue;
#else
cnt = ttydriv(c, &ttybuf);
if (ttyflow && (mode != CMD_MODE))
go(); /* display pending chars */
if (cnt == 0)
continue;
#endif /* FLOW */
switch(mode){
case CMD_MODE:
(void)cmdparse(cmds,ttybuf);
fflush(stdout);
break;
case CONV_MODE:
if(current->parse != NULLFP)
(*current->parse)(ttybuf,cnt);
break;
}
#if defined(FORKSHELL) && defined(SYS5)
if(mode == CMD_MODE && !shellpid)
#else
if(mode == CMD_MODE)
#endif
{
if(noprompt) /* k35 */
noprompt = 0;
else{
printf(prompt);
fflush(stdout);
}
}
} /* while */
}
void
raw()
{
ttymode = TTY_RAW;
}
void
cooked()
{
ttymode = TTY_COOKED;
}
#ifdef CUTE_FTP
void
echo()
{
ttyecho = TTY_ECHO;
}
void
noecho()
{
ttyecho = TTY_NOECHO;
}
#endif
/* Accept characters from the incoming tty buffer and process them
* (if in cooked mode) or just pass them directly (if in raw mode).
* Returns the number of characters available for use; if non-zero,
* also stashes a pointer to the character(s) in the "buf" argument.
*/
/*Control-R added by df for retype of lines - useful in Telnet */
/*Then df got impatient and added Control-W for erasing words */
/* Control-V for the literal-next function, slightly improved
* flow control, local echo stuff -- hyc */
/* editing, put this in edit.hlp for online reminder:
Editing for commands
^E redisplay last line
^A backup one word
^S backup one char
^D fwd one char
^F fwd one word
Other editing:
^R redisplay current line buffer
^W erase word backward
Special characters:
^V next char literal
^U or ^Y kill line
^H or DEL destructive backspace
*/
/* moved to global scope so kaktc (session.c) could reset pointer */
char linebuf[KBLINSIZ];
char *kbcp = linebuf;
int
ttydriv(c,buf)
char c;
char **buf;
{
#ifdef EDIT
static char lastline[KBLINSIZ];
static char *ep = linebuf;
static int editing;
int i;
#endif
int erase = FALSE;
char *rp ;
int cnt;
extern int unix_line_mode; /* k35c */
#ifdef EDIT
if(*lastline == '\0') /* only happens first time through */
*lastline = '\015';
#endif
if(buf == (char **)0)
return 0; /* paranoia check */
cnt = 0;
switch(ttymode){
case TTY_LIT:
ttymode = TTY_COOKED; /* Reset to cooked mode */
*kbcp++ = c; /* run a slight risk of array violation here */
#ifdef UNIX
putchar('.'); /* Terminal may prefer no Ctrl-chars */
#else
putchar(c); /* I know it isn't noxious on MS-DOS */
#endif
break;
case TTY_RAW:
/* special problem with sending password when telnetting to a
* station that turns echo off. We need to keep cnt = 0 until
* we finish line. We must complete password without changing
* sessions, etc. Not worrying about buffer overwrite, etc. k35c
*/
if(c == '\015' || c == '\012'){ /* k35a telnet password needs */
printf("\n"); /* newline. FTP cli doesn't */
*kbcp++ = '\015';
if(!unix_line_mode)
*kbcp++ = '\012';
cnt = (kbcp - linebuf); /* now can tell world about it */
kbcp = linebuf;
}else
*kbcp++ = c;
break;
case TTY_COOKED:
/* Perform cooked-mode line editing */
switch(c & 0x7f){
case '\015': /* Terminal may generate either */
case '\012':
*kbcp++ = '\015';
*kbcp++ = '\012'; /* guaranteed to bust array! K5JB */
printf("\n");
cnt = kbcp - linebuf;
#ifdef EDIT
for(i=0;i<KBLINSIZ;i++){ /* save in lastline */
if(linebuf[i] == '\012') /* will use '\r' as marker */
break;
lastline[i] = linebuf[i];
}
editing = FALSE;
ep = linebuf;
#endif
kbcp = linebuf;
break;
case CTLU:
case CTLY: /* Line kill - also active with no echo */
erase = TRUE; /* borrow an existing int */
#ifdef EDIT
case CTLE: /* redisplay last line */
if(editing && !erase)
break;
#endif
#ifdef CUTE_FTP
if(!ttyecho)
kbcp = linebuf;
else
#endif
while(kbcp != linebuf){
kbcp--;
printf("\b \b");
}
if(erase)
break;
#ifdef EDIT
#ifdef CUTE_FTP
if(!ttyecho) /* don't need to edit */
break; /* when no echo */
#endif
kbcp = linebuf;
for(i=0;i<KBLINSIZ;i++){
if(lastline[i] == '\015')
break;
linebuf[i] = lastline[i];
putchar(linebuf[i]);
kbcp++;
}
if(i){
ep = &linebuf[i];
editing = TRUE;
}
break;
case CTLD: /* forward one char */
if(editing && kbcp < ep){
putchar(*kbcp++);
}
break;
case CTLF: /* forward one word */
if(editing)
while(kbcp < ep){
putchar(*kbcp++);
if(isspace(*kbcp)){ /* isspace() costs 258 bytes but it is*/
if(kbcp < ep) /* already used in smtpserv.c */
putchar(*kbcp++);
break;
}
}
break;
case CTLS: /* backward one char */
if (editing && kbcp != linebuf){
printf("\b");
kbcp--;
}
break;
#endif
case RUBOUT:
case '\b': /* Backspace - note this works when no echo */
if(kbcp != linebuf){
kbcp--;
printf("\b \b"); /* this isn't cool if no ttyecho, but */
}
break;
case CTLR: /* print line buffer */
#ifdef CUTE_FTP
if(!ttyecho)
break;
#endif
printf("^R\n");
rp = linebuf ;
while (rp < kbcp)
putchar(*rp++);
break ;
case CTLV:
ttymode = TTY_LIT;
break;
case CTLW: /* erase word backward */
erase = TRUE;
case CTLA: /* move cursor back one word */
#ifdef CUTE_FTP
if(!ttyecho)
break;
#endif
if(kbcp != linebuf && isspace(*(kbcp-1))){/* not at end of line */
kbcp--; /* back up onto the space */
putchar('\b');
}
while (kbcp != linebuf) {
kbcp--;
if(erase)
printf("\b \b") ;
else
printf("\b");
if (isspace(*kbcp)) {
putchar(*kbcp++);
break;
}
}
break ;
default: /* Ordinary character */
*kbcp++ = c;
/* ^Z is a common screen clear character - K5JB */
#ifdef CUTE_FTP
if (ttyecho && (c != CTLZ))
#else
if (c != CTLZ)
#endif
putchar(c);
/* if line is too long, we truncate it */
if(kbcp > &linebuf[KBLINSIZ - 3]){ /* room for \r\n
but NO null */
linebuf[KBLINSIZ - 2] = '\015';
linebuf[KBLINSIZ - 1] = '\012';
cnt = KBLINSIZ;
kbcp = linebuf;
}
break;
} /* switch ch in case TTY_COOKED */
} /* switch ttymode */
if(cnt > 0)
*buf = linebuf;
else
*buf = (char *)0; /* K5JB */
#ifdef FLOW
if(kbcp > linebuf)
ttyflow = 0;
else
ttyflow = 1;
#endif
fflush(stdout);
return cnt;
}