From: Brett Gordon
authorAlan Cox <alan@linux.intel.com>
Tue, 3 May 2016 15:30:57 +0000 (16:30 +0100)
committerAlan Cox <alan@linux.intel.com>
Tue, 3 May 2016 15:30:57 +0000 (16:30 +0100)
This patch adds dwterm and dwgetty

(dropped them from the ucp script as they are only relevant to COCO at this
 point) - Alan

Applications/dw/Makefile.6809
Applications/dw/dwgetty.c [new file with mode: 0644]
Applications/dw/dwterm.c [new file with mode: 0644]

index eba8d48..e2f3250 100644 (file)
@@ -15,7 +15,7 @@ CRT0 = ../../Library/libs/crt0_6809.o
 .SUFFIXES: .c .o
 
 
-SRCS  = dw.c
+SRCS  = dw.c dwgetty.c dwterm.c
 
 OBJS = $(SRCS:.c=.o)
 
diff --git a/Applications/dw/dwgetty.c b/Applications/dw/dwgetty.c
new file mode 100644 (file)
index 0000000..55cd048
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+  A Very simple getty for starting a telnet session over Drivewire 4.
+
+*/
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <utmp.h>
+/* for getty/login */
+#include <pwd.h>
+#include <signal.h>
+#include <grp.h>
+#include <paths.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+
+int port;
+int tries=3;
+char *port_txt;
+char *listenMsg="tcp listen ";
+char *join="tcp join ";
+char conn;
+struct termios new;
+
+static void spawn_login(struct passwd *, const char *, const char *);
+static pid_t getty(const char *, const char *, int);
+
+static struct utmp ut;
+
+char buff[128];
+
+void doEcho( int f )
+{
+       unsigned char e[3]={ 255, 253, 1 };
+       write( f, e, 3 );
+}
+
+void dontEcho( int f )
+{
+       unsigned char e[3]={ 255, 254, 1 };
+       write( f, e, 3 );
+}
+
+void willEcho( int f )
+{
+       unsigned char e[3]={ 255, 251, 1 };
+       write( f, e, 3 );
+}
+
+void wontEcho( int f )
+{
+       unsigned char e[3]={ 255, 252, 1 };
+       write( f, e, 3 );
+}
+
+void getrply( int f )
+{
+       unsigned char e[3];
+       read( f, e, 3 );
+}
+
+
+#define crlf()   write(1, "\r\n", 2)
+
+void sigalarm(int sig)
+{
+       return;
+}
+
+void putstr(char *str)
+{
+       write(1, str, strlen(str));
+}
+
+int showfile(char *fname)
+{
+       int fd, len;
+       char buf[80];
+
+       fd = open(fname, O_RDONLY);
+       if (fd >= 0) {
+               do {
+                       len = read(fd, buf, 80);
+                       write(1, buf, len);
+               } while (len > 0);
+               close(fd);
+               return 1;
+       }
+       return 0;
+}
+
+static char *env[10];
+static int envn;
+
+static void envset(const char *a, const char *b)
+{
+       int al = strlen(a);
+       static char hptr[5];
+       /* May unalign the memory pool but we don't care by this point */
+       char *tp = sbrk(al + strlen(b) + 2);
+       if (tp == (char *) -1) {
+               putstr("out of memory.\n");
+               return;
+       }
+       strcpy(tp, a);
+       tp[al] = '=';
+       strcpy(tp + al + 1, b);
+       env[envn++] = tp;
+}
+
+static char *argp[] = { "sh", NULL };
+
+static void spawn_login(struct passwd *pwd, const char *tty, const char *id)
+{
+       char *p, buf[50];
+       /* utmp */
+       ut.ut_type = USER_PROCESS;
+       ut.ut_pid = getpid();
+       strncpy(ut.ut_line, tty+5, UT_LINESIZE);
+       strncpy(ut.ut_id, id, 2);
+       time(&ut.ut_time);
+       strncpy(ut.ut_user, pwd->pw_name, UT_NAMESIZE);
+       pututline(&ut);
+       endutent();
+
+       /* We don't care if initgroups fails - it only grants extra rights */
+       initgroups(pwd->pw_name, pwd->pw_gid);
+
+       /* But we do care if these fail! */
+       if (setgid(pwd->pw_gid) == -1 ||
+               setuid(pwd->pw_uid) == -1)
+                       _exit(255);
+       signal(SIGINT, SIG_DFL);
+
+       /* setup user environment variables */
+
+       envset("LOGNAME", pwd->pw_name);
+       envset("HOME", pwd->pw_dir);
+       envset("SHELL", pwd->pw_shell);
+
+       /* home directory */
+
+       if (chdir(pwd->pw_dir))
+               putstr("login: unable to change to home directory, using /\n");
+
+       /* show the motd file */
+
+       if (!showfile("/etc/motd"))
+               crlf();
+
+       /* and spawn the shell */
+
+       strcpy(buf, "-");
+       if ((p = strrchr(pwd->pw_shell, '/')) != NULL)
+               strcat(buf, ++p);
+       else
+               strcat(buf, pwd->pw_shell);
+
+       argp[0] = buf;
+       argp[1] = NULL;
+
+       execve(pwd->pw_shell, (void *) argp, (void *) env);
+       putstr("login: can't execute shell\n");
+       exit(1);
+}
+
+/* 
+   getpass.c implimented for TELNET
+*/
+
+#define EOF    (-1)
+
+static int __getchar(int fd)
+{
+       static char ch;
+       return (read(fd, &ch, 1) == 1) ? ch : EOF;
+}
+
+static char *_gets(int fd, char *buf, int len)
+{
+       int ch, i = 0;
+
+       while (i < len) {
+               if ((ch = __getchar(fd)) == EOF && i == 0)
+                       return NULL;
+               if (ch == '\n' || ch == '\r')
+                       break;
+               buf[i++] = ch;
+       }
+       buf[i] = 0;
+       return buf;
+}
+
+char *getpass(char *prompt)
+{
+       static char result[128];
+
+       /* display the prompt */
+       write(1, prompt, strlen(prompt));
+
+       willEcho(1);
+       getrply(0);
+       /* read the input */
+       if (_gets(0, result, sizeof(result) - 1) == NULL)
+       result[0] = 0;
+       wontEcho(1);
+       /* The newline isn't echoed as we have echo off, so we need to
+          output it as the end of the task */
+       write(1, "\n", 1);
+       return result;
+}
+
+
+
+/*
+ *     Internal implementation of "getty" and "login"
+ */
+static pid_t getty(const char *ttyname, const char *id, int fdtty)
+{
+       struct passwd *pwd;
+       const char *pr;
+       char *p, buf[50], salt[3];
+       char hn[64];
+       gethostname(hn, sizeof(hn));
+
+       for (;;) {
+               close(0);
+               close(1);
+               close(2);
+               setpgrp();
+               setpgid(0,0);
+
+               /* here we are inside child's context of execution */
+               envset("PATH", "/bin:/usr/bin");
+               envset("CTTY", ttyname);
+
+               /* make stdin, stdout and stderr point to fdtty */
+               
+               dup(fdtty);
+               dup(fdtty);
+               dup(fdtty);
+               close(fdtty);
+
+               /* display the /etc/issue file, if exists */
+               showfile("/etc/issue");
+               if (*hn) {
+                       putstr(hn);
+                       putstr(" ");
+               }
+               /* loop until a valid user name is entered
+                * and a shell is spawned */
+
+               for (;;) {
+                       putstr("login: ");
+                       while (read(0, buf, 20) < 0);   /* EINTR might happens because of the alarm() call below */
+                       
+                       if ((p = strchr(buf, '\n')) != NULL)
+                               *p = '\0';      /* strip newline */
+
+                       pwd = getpwnam(buf);
+
+                       if (pwd) {
+                               if (pwd->pw_passwd[0] != '\0') {
+                                       p = getpass("Password: ");
+                                       salt[0] = pwd->pw_passwd[0];
+                                       salt[1] = pwd->pw_passwd[1];
+                                       salt[2] = '\0';
+                                       pr = crypt(p, salt);
+                               } else {
+                                       pr = "";
+                               }
+                               if (strcmp(pr, pwd->pw_passwd) == 0)
+                                       spawn_login(pwd, ttyname, id);
+                       }
+                       if( !--tries ){
+                               putstr("\nToo Many Attempts\n\n");
+                               exit(1);
+                       }
+                       putstr("\nLogin incorrect\n\n");
+                       signal(SIGALRM, sigalarm);
+                       alarm(2);
+                       pause();
+               }
+       }
+}
+
+
+
+void pute( char *mess )
+{
+       write( 2, mess, strlen(mess) );
+}
+
+
+// dwgetty tty       port
+// dwgetty /dev/tty3 6809
+int main( int argc, char *argv[])
+{
+       int f;
+
+
+       if( argc<3){
+               pute("usage: dwgetty tty port\n" );
+               exit(-1);
+       }
+
+       port=atoi( argv[2] );
+       port_txt=argv[2];
+
+       f=open( argv[1], O_RDWR );
+       if( ! f ){ 
+               pute("Cannot open device file\n" );
+               exit(-1);
+       }
+
+       tcgetattr( f, &new );
+       new.c_iflag |= ICRNL;
+       new.c_iflag &= ~IGNCR;
+       // new.c_oflag |= OPOST | ONLCR;
+       //      new.c_oflag &= ~ONLCR;
+       new.c_lflag &= ~ECHO;
+       tcsetattr( f, TCSANOW, &new );
+
+       int i;
+       int len;
+
+       write(f,listenMsg,strlen(listenMsg) );
+       write(f,port_txt,strlen(port_txt) );
+       write(f,"\r",1);
+
+       for( i=0; i<4; i++){
+               len=read(f,buff,128);
+       }
+       conn=buff[0];
+
+       write(f, join, strlen(join) );
+       write(f, &conn, 1 );
+       write(f, "\r", 1 );
+       len=read(f,buff,128);
+
+               new.c_iflag |= IGNCR;
+       tcsetattr( f, TCSANOW,  &new );
+       char c[2];
+       c[0]='0';
+       c[1]=argv[1][strlen(argv[1])-1];
+       getty( argv[1], c, f );
+}
+
+
diff --git a/Applications/dw/dwterm.c b/Applications/dw/dwterm.c
new file mode 100644 (file)
index 0000000..706a493
--- /dev/null
@@ -0,0 +1,510 @@
+/* dwtelnet - Drivewire - raw Telnet
+ */
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+#define TESC 0x19
+#define ESC 0x1b
+
+
+char ibuf[256];
+int opos=0;
+
+int flags;
+struct termios prior,new;
+struct termios lprior,lnew;
+int fddw;
+int para[4]={0,0,0,0};
+int no=0;
+char colors[8]={
+       '0', '2', '4', '6',
+       '1', '3', '5', '7'
+};
+
+int linemode=0;
+int lecho=-1;
+int pflag=0;
+int hex=0;
+int del=0;
+int crnl=-1;
+int fc=7;
+int bc=0;
+int inten=0;
+
+
+void puterr( char *str ){
+       write(2, str, strlen(str));
+}
+
+void putstr( char *str ){
+       write(1, str, strlen(str));
+}
+
+int isnum( char c ){
+       if( c>='0' && c<='9' ) return 1;
+       return 0;
+}
+
+int tonum( char c ){
+       return c-'0';
+}
+
+void out52( char c ){
+       write(1, "\x1b", 1 );
+       write(1,&c, 1 );
+}
+
+void out52n( char c, char n ){
+       out52( c );
+       write(1,&n, 1 );
+}
+
+void out52nn( char c, char n, char m){
+       out52( c );
+       write(1,&n,1);
+       write(1,&m,1);
+}
+
+
+char cconv( char c ){
+       return colors[c];
+}
+
+
+/* check for matching fore/background colors w/ intensity bit
+   we can't do intensity - so text disappears */
+void ckint(){
+       if( (fc ==  bc)  &&  inten ){
+               fc = fc + 1 & 0x7 ;
+               out52n( 'b', fc );
+       }
+}
+
+/* Send a char to the console, processing for ANSI/TELNET chars */
+void charout( char c ){
+       static char mode=0;
+       int i;
+
+       switch( mode ){
+               /* normal mode */
+       case 0: 
+               if( c == 255 ){
+                       mode=3;
+                       return;
+               }
+               if( c != ESC )  write( 1, &c ,1 );
+               else{ 
+                       mode=1;
+               }
+               return;
+               /* ESC detected */
+       case 1:
+               if( c=='[' ){
+                       mode=2;
+                       return;
+               }
+               return;
+               /* Multi-byte detected */
+       case 2: 
+               if( isnum(c) ){
+                       para[no]=para[no]*10+tonum(c);
+                       return;
+               }
+               if( c == ';' ){
+                       no++;
+                       return;
+               }
+               no++;
+               goto final;
+               /* Telnet IAC detected */
+       case 3:
+               switch( c ){
+               case 255:
+                       write(1,&c,1);
+                       mode=0;
+                       return;
+
+               case 251:
+                       mode=5;
+                       return;
+               case 252:
+                       mode=6;
+                       return;
+               case 253:
+               case 254:
+                       if(hex) printf("<IAC><%x>",c);
+                       mode=4;
+                       return;
+               }
+               mode=0;
+               return;
+               /* send Telnet's WILLNOTs to server */
+       case 4:
+               if( hex )printf("<%x>\n", c );
+               write( fddw, "\xff\xfc",2);
+               write( fddw, &c, 1 );
+               mode = 0;
+               return;
+               /* received a WILL */
+       case 5:
+               if( c == 1 ){
+                       lecho = 0;
+                       //write(fddw,"\xff\xfd",2);
+                       //write(fddw, &c, 1 );
+                       mode = 0;
+                       return;
+               }
+               write( fddw,"\xff\xfe",2);
+               write( fddw, &c, 1);
+               mode = 0;
+               return;
+               /* received a WONT */
+       case 6:
+               if( hex ) printf("opt<%x>\n", c );
+               if( c == 1 ) lecho = -1;
+               else{
+                       write( fddw, "\xff\xfe", 2 );
+                       write( fddw, &c, 1 );
+               }
+               mode = 0;
+               return;
+
+       }
+       /* and the trailing command */
+ final:
+       //      printf("DEBUG: %d %d %d %c\n", para[0], para[1], para[2], c);
+       switch( c ){
+       case 'J':
+               if( para[0] == 2 ){
+                       out52( 'H' );
+                       out52( 'J' );
+                       break;
+               }
+               if( para[1] == 0 ){
+                       out52( 'J' );
+                       break;
+               }
+       case 'H':
+       case 'f':
+               if( para[0]==0 && para[1]==0 ){
+                       out52( 'H' );
+                       break;
+               }
+               if( para[0]==0 ) para[0]=1;
+               if( para[1]==0 ) para[1]=1;
+               out52nn( 'Y', para[0]+' ', para[1]+' ');
+               break;
+       case 'K':
+               if( para[0] == 0 ){
+                       out52( 'K');
+                       break;
+               }
+       case 'm':
+               for( i=0; i<no; i++ ){
+                       if( para[i]>=30 && para[i]<=37 ){
+                               fc=cconv(para[i]-30);
+                               out52n( 'b', fc );
+                               ckint();
+                       }
+                       if( para[i]>=40 && para[i]<=47 ){
+                               bc=cconv(para[i]-40);
+                               out52n( 'c', bc );
+                               ckint();
+                       }
+                       if( para[i]==0 ){
+                               out52n( 'b', '4' );
+                               out52n( 'c', '0' );
+                               inten=0;
+                       }
+                       if( para[i]==1 ){
+                               inten=1;
+                               ckint();
+                       }               
+               }
+               break;
+       case 'C':
+       case 'D':
+       case 'A':
+       case 'B':
+               if( para[0]==0 ) para[0]=1;
+               for( i=0; i<para[0]; i++) out52(c);
+               break;
+       case 'n':
+               if( para[0]==6 ){
+                       write(fddw,"\x1b[1;1R",6);
+                       out52( 'H' );
+                       out52( 'J' );
+               } 
+               break;
+               //      default:
+
+       }
+       para[0]=0;
+       para[1]=0;
+       para[2]=0;
+       para[3]=0;
+       no=0;
+       mode = 0;
+}
+
+/* print string to console under ANSI/TELNET */
+int mywrite( char *ptr, int len ){
+       int i=len;
+       while( i-- ) charout( *ptr++ );
+       return len;
+}
+
+void quit(){
+       tcsetattr( fddw, TCSANOW, &prior );
+       tcsetattr( 0, TCSANOW, &lprior );
+       fcntl(0, F_SETFL, flags );
+       close( fddw );
+       exit(0);
+}
+
+/* Add string to input buffer */
+void addstr(char *s){
+       for( ; ibuf[opos++]=*s; s++ )
+               if( lecho ) write(1,s,1);
+       opos--;
+}
+
+void printd( char *s ){
+       while( *s ) write( 1, s++, 1);
+       write( 1, "\n", 1 );
+}
+
+void printhelp( void ){
+       printd( "l linemode toggle" );
+       printd( "e echo toggle");
+       printd( "q quit");
+       printd( "h IAC TELNET hex debugging");
+       printd( "n NL / CRNL");
+       printd( "^A send ^A to remote");
+}
+
+/* Read from standard input, nonblocking */
+int myread( void ){
+       static int icount=0;
+       static int ipos=0;
+       static char kbuf[256];
+       static int mode=0;
+       static int cmode=0;
+       int l;
+
+       switch( mode ){
+       case 0: // waiting for input buffer to fill middle 
+               l=read( 0, kbuf, 256 );
+               if( ! l ) return 0;
+               if( l < 0 ){
+                       if( errno == EAGAIN ){
+                               return 0;
+                       }
+                       else {
+                               close(fddw);
+                               quit();
+                       }
+               }
+               ipos=0;
+               icount=l;
+               mode=1;
+       case 1: // processing middle buffer to input buffer
+               for( ; ipos<icount; ipos++ ){
+                       char c=kbuf[ipos];
+                       if( cmode ){
+                               switch( c ){
+                               case '1':
+                                       addstr( "tcp connect " );
+                                       break;
+                               case '2':
+                                       addstr( "nostalgiamud.l-w.ca 4000");
+                                       break;
+                               case '3':
+                                       addstr( "aardmud.org 23" );
+                                       break;
+                               case '4':
+                                       addstr( "vert.synchro.net 23" );
+                                       break;
+                               case '5':
+                                       addstr( "madworld.bounceme.net 6400");
+                                       break;
+                               case 'l':
+                                       linemode = ~linemode ;
+                                       break;
+                               case 'e':
+                                       lecho = ~lecho;
+                                       break;
+                               case 'q':
+                                       quit();
+                               case 'h':
+                                       hex= ~hex;
+                                       break;
+                               case 'd':
+                                       del= ~del;
+                                       break;
+                               case 'n':
+                                       crnl= ~crnl;
+                                       break;
+                               case 1:
+                                       ibuf[opos++]=1;
+                                       break;
+                               case '?':
+                                       printhelp();
+                                       break;
+                               }
+                               cmode=0;
+                               continue;
+                       }
+                       if( c == 1 ){
+                               cmode=1;
+                               continue;
+                       }
+                       if( linemode ){
+                               if( c == 8 ){
+                                       if( opos ){
+                                               opos--;
+                                               write(1,"\b \b",3);
+                                               continue;
+                                       }
+                                       continue;
+                               }
+                               write(1,&c,1);
+                               if( c == '\n' ){
+                                       int t=opos;
+                                       opos=0;
+                                       ibuf[t]=c;
+                                       ipos++;
+                                       return ++t;
+                               }
+                               ibuf[opos++]=c;
+                               continue;
+                       }
+                       if( lecho ) write(1,&c,1);
+                       if( (c == 8) && del ){
+                               ibuf[opos++]=127;
+                               continue;
+                       }
+                       if( (c== 0x0a) && crnl ){
+                               ibuf[opos++]=0x0d;
+                               ibuf[opos++]=0x0a;
+                               continue;
+                       }
+                       ibuf[opos++]=c;
+                       continue;
+               }
+               mode=0;
+               if( ! linemode ){
+                       int t=opos;
+                       opos=0;
+                       return t;
+               }
+               return 0;
+       }
+}
+
+my_open( int argc, char *argv[]){
+       if( !argv[optind] ){
+               fddw=open("/dev/tty3", O_RDWR|O_NDELAY);
+       }
+       else{
+               fddw=open(argv[optind], O_RDWR|O_NDELAY);
+       }
+       if( ! fddw ){
+               puterr( "Cannot open device\n" );
+               exit(-1);
+       }
+       
+       tcgetattr( fddw, &prior );
+       tcgetattr( fddw, &new );
+       new.c_iflag &= ~ICRNL;
+       new.c_lflag &= ~ECHO;
+       new.c_lflag &= ~ICANON;
+       new.c_oflag &= ~OPOST;
+       tcsetattr( fddw, TCSANOW, &new );
+
+
+}
+
+int main( int argc, char *argv[]){
+       int len;
+       int opt;
+
+       while( (opt=getopt( argc, argv, "p" ))>-1 ){
+               switch( opt ){
+               case 'p':
+                       pflag=1;
+                       break;
+               }
+       }
+
+
+       tcgetattr( 0, &lprior );
+
+       my_open( argc, argv );
+
+       flags = fcntl(0, F_GETFL, 0);
+       fcntl(0, F_SETFL, flags | O_NDELAY );
+
+
+       tcgetattr( 0, &lnew );
+       lnew.c_lflag &= ~ICANON;
+       lnew.c_lflag &= ~ECHO;
+       tcsetattr( 0, TCSANOW, &lnew );
+
+       printf("Use Cntl-A ? for help.\n");
+
+       while(1){
+               char *pos=ibuf;
+               len=myread();
+               while( len > 0 ){
+                       int ret = write( fddw, pos, len );
+                       if( ret < 0 ){ 
+                               if( errno == EAGAIN ){
+                                       ret=0;
+                               }
+                               else {
+                                       close(fddw);
+                                       if( pflag ){
+                                               my_open( argc, argv );
+                                               continue;
+                                       }
+                                       else quit();
+                               }
+                       }
+                       len=len-ret;
+                       pos+=ret;
+               }
+               len=read( fddw, ibuf, 127 );
+               if( len < 0 ){
+                       if( errno != EAGAIN ){
+                               close(fddw);
+                               if( pflag ){
+                                       my_open( argc, argv );
+                                       continue;
+                               }
+                               else quit();
+                       }
+               }
+               pos = ibuf;
+               while( len > 0){
+                       int ret = mywrite( pos, len );
+                       if( ret < 0 ){
+                               if( errno == EWOULDBLOCK ){
+                                       ret=0;
+                               }
+                               else quit();
+                       }
+                       len=len-ret;
+                       pos+=ret;
+               }
+       }
+}
+
+
+