|
|
researchv10 Norman
/*
* DCON
* Connect terminal to Datakit network
* Operation is line-at-a-time with remote echo.
*/
#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <dk.h>
#include <errno.h>
#define CEOT 04
struct sgttyb savloc;
struct tchars savechars;
struct ltchars lsavechars;
struct ltchars nlchars = { -1, -1, -1, -1, -1, -1 };
char intrchar = 0177;
char quitchar = '\\'&037;
int rem; /* remote descriptor */
extern int dkp_ld, cdkp_ld;
#define NOLD (-1) /* no line discipline */
int which_ld = NOLD;
char serv[32]; /* .login, .dcon, etc. */
int autologin;
int noflush;
#define LINSIZ 128
char *space = " \r\t\n";
int neofs = 0; /* die when greater than N */
int sigint();
extern int dkverbose ;
extern char *strtok();
extern char *strchr();
extern char *strcpy();
extern char *strcat();
extern char *malloc();
extern FILE *scriptopen();
extern char *strchr();
SIG_TYP savint, savquit;
intcatch(){ /* catch interrupts, turn them into rubouts */
signal(SIGINT, intcatch);
ioctl(rem, TIOCFLUSH, 0);
write(rem, &intrchar, 1);
ioctl(rem, TIOCFLUSH, 0);
ioctl(0, TIOCFLUSH, 0);
}
quitcatch(){ /* catch quits, turn them into FS's */
ioctl(0, TIOCFLUSH, 0);
signal(SIGQUIT, quitcatch);
write(rem, &quitchar, 1);
}
main(argc,argv)
char **argv;
{
int i, traffic;
char dialstr[64] ;
int scriptlogin;
FILE *script;
savetty();
which_ld = dkp_ld;
strcpy(serv, ".dcon");
traffic = 0;
autologin = 1;
scriptlogin = 0;
for(i=1; i<argc && argv[i][0]=='-'; i++) {
switch(argv[i][1]) {
case 'u':
which_ld = NOLD;
continue;
case 'f':
noflush++;
continue;
case 's':
scriptlogin = 1;
continue;
case 'l':
serv[0] = '\0';
autologin = 0;
continue;
case 'd':
case 'b':
which_ld = dkp_ld;
continue;
case 'c':
which_ld = cdkp_ld;
continue;
case 'v':
dkverbose++ ;
continue ;
default:
goto Usage;
}
}
if (i>=argc){
Usage:
quit("usage: dcon [-lvs] hostname");
}
savint = signal(SIGINT, intcatch);
savquit = signal(SIGQUIT, quitcatch);
/*
* request circuit to host.
*/
strcpy(dialstr, argv[i]) ;
if(strchr(dialstr, '.'))
serv[0] = '\0';
if(scriptlogin) {
script = scriptopen(dialstr);
if(script == NULL)
quit("bad script");
}
strcat(dialstr, serv);
rem = tdkdial(dialstr, traffic);
if (rem < 0) {
char msg[64];
extern char *dkerror;
sprintf(msg, "%s; call failed", dkerror);
quit(msg);
}
/*
* turn on line discipline according to protocol.
*/
if(dkverbose) printf("pushing %d...\n", which_ld);
if (which_ld != NOLD
&& dkproto(rem, which_ld) < 0)
quit("can't turn on datakit protocol");
if (autologin){
if (tdklogin(rem) < 0)
quit("can't log in") ;
if(dkverbose) printf("logged in\n");
}
if(scriptlogin) {
if (dkscript(rem,script) < 0)
quit("can't log in") ;
if(dkverbose) fprintf(stderr,"logged in\n");
}
settty();
scan(rem);
/*NOTREACHED*/
}
scan(f)
int f;
{
extern errno;
fd_set rd;
ioctl(f, DIOCSTREAM, (char *)0);
FD_ZERO(rd);
for (;;) {
FD_SET(f, rd);
FD_SET(0, rd);
if (select(f+1, &rd, (fd_set *)0, 2000) == -1) {
if(errno == EINTR)
continue;
quit("select failed");
}
if (FD_ISSET(0, rd))
keyboard();
if (FD_ISSET(f, rd))
remote();
}
}
quit(s)
char *s;
{
printf("dcon: %s\n", s);
signal(SIGINT, SIG_DFL);
resettty();
if (noflush==0)
ioctl(rem, TIOCFLUSH, 0);
close(rem);
exit(strcmp(s, "eof"));
}
/*
* Scan data from keyboard, looking for escape lines.
*/
keyboard()
{
register c;
register cc;
register char *bp;
register char *be, *obp;
char buf[1024];
static char line[128];
static char *linep = &line[0];
static col = 0;
cc = read(0, buf, sizeof buf);
if (cc == 0)
quit("eof");
if (cc < 0) {
if (errno == EINTR)
return;
quit("read error on file descriptor 0");
}
be = buf+cc;
bp = obp = buf;
while(bp < be) {
c = *bp++;
if (col==0 && c=='~') {
*linep++ = c;
col = 1;
resettty();
write(1, linep-1, 1);
continue;
}
col++;
if (c=='\r')
c = '\n';
if (linep>line) {
*linep++ = c;
if (c==savloc.sg_kill)
write(1, "\n", 1);
if (c==savloc.sg_erase)
linep -= 2;
if (c==savloc.sg_kill || linep<=line) {
linep = line;
settty();
col = 0;
obp = bp;
}
}
if (c=='\n') {
col = 0;
if (linep > line) {
*linep = '\0';
if (escape(line+1))
write(rem, line+1, linep-line-1);
obp = bp;
linep = line;
settty();
}
}
}
if (bp>obp && linep==line)
write(rem, obp, bp-obp);
}
/*
* Send data from remote machine to standard output (trivial)
*/
remote(){
char buf[1024];
register n;
n = read(rem, buf, sizeof buf);
if(n < 0 && errno == EINTR)
return;
if(n <= 0){
if(dkverbose) printf("EOF %d\r\n", neofs);
if(neofs++ > 4){
quit("Eof\r");
}
return;
}
neofs = 0;
write(1, buf, n);
}
escape(line)
register char *line;
{
switch(*line++) {
case '!':
cunix(line);
return(0);
case '.':
case CEOT:
quit("eof");
case 'b':
ioctl(rem, TIOCSBRK, 0);
return(0);
default:
return(1);
}
}
cunix(prog)
char *prog;
{
register int upid;
int retcode;
if ((upid = fork()) == 0) {
signal(SIGINT, savint);
signal(SIGQUIT, savquit);
resettty();
if (*prog == '\n')
execl("/bin/sh", "sh", "-i", 0);
else
execl("/bin/sh","sh","-c",prog,0);
exit(0100);
}
if (upid < 0)
printf("can't fork\n");
else {
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
while((wait(&retcode) !=upid))
;
}
signal(SIGINT, intcatch);
signal(SIGQUIT, quitcatch);
settty();
printf("!!\n");
}
dkscript(r,f)
FILE *f;
{
char sline[LINSIZ];
while(fgets(sline,100,f)) {
if(rget(r,strtok(sline,space)) < 0)
return(-1);
if(fgets(sline,100,f)==0)
return(-1);
if(dkverbose) fprintf(stderr,"sending %s",sline);
write(r,sline,strlen(sline));
}
return(1);
}
rget(r,s)
char *s;
{
int i;
char buf[LINSIZ];
int brkchr = s[strlen(s)-1];
for(;;) {
for(i=0; ; i++) {
if(i>=LINSIZ-2) {
buf[i] = 0;
strcpy(buf,&buf[LINSIZ/2]);
i = strlen(buf);
}
if(read(r,&buf[i],1) <= 0)
return(-1);
buf[i] &= 0177;
if(buf[i] == brkchr)
break;
}
buf[i+1] = 0;
while(i>=0 && buf[i] && !strchr(space,buf[i]))
i--;
i++;
if(dkverbose) fprintf(stderr,"check '%s' vs '%s'\n",s,&buf[i]);
if(strcmp(s,&buf[i]) == 0)
return(1);
}
/*NOTREACHED*/
}
FILE *
scriptopen(s)
char *s;
{
FILE *script = fopen(s, "r");
if(script == NULL)
return(NULL);
if(fgets(s,LINSIZ,script) == NULL)
return(NULL);
if(dkverbose) fprintf(stderr,"calling %s\n",s);
strtok(s,"\n");
return script;
}
savetty()
{
if (ioctl(0, TIOCGETC, &savechars) >= 0) {
intrchar = savechars.t_intrc;
quitchar = savechars.t_quitc;
}
ioctl(0, TIOCGLTC, &lsavechars);
ioctl(0, TIOCGETP, &savloc);
}
settty()
{
struct sgttyb s;
s = savloc;
s.sg_flags &=~ (CRMOD|ECHO|XTABS);
s.sg_flags |= CBREAK;
ioctl(0, TIOCSETP, &s);
ioctl(0, TIOCSLTC, &nlchars);
}
resettty()
{
ioctl(0, TIOCSETP, &savloc);
ioctl(0, TIOCSLTC, &lsavechars);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.