pax_global_header00006660000000000000000000000064142465364770014534gustar00rootroot0000000000000052 comment=bee4db6507fdf31bddfa98d26a673e135dfd28ad drawterm-9front-0~git20220608.bee4db6/000077500000000000000000000000001424653647700172415ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/LICENSE000066400000000000000000000021671424653647700202540ustar00rootroot00000000000000Copyright © 2021 Plan 9 Foundation Portions Copyright © 2005 Russ Cox, MIT Portions Copyright © 20XX 9front authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. drawterm-9front-0~git20220608.bee4db6/Make.android000066400000000000000000000024621424653647700214640ustar00rootroot00000000000000# Android SDKPREFIX=$(HOME)/Android/Sdk JAVA_HOME=/usr OBJS=lib/arm64-v8a/libdrawterm.so lib/armeabi-v7a/libdrawterm.so lib/x86/libdrawterm.so lib/x86_64/libdrawterm.so all: drawterm.apk clean: rm -f *.apk lib/*/*.so lib/arm64-v8a/libdrawterm.so: CONF=android-arm64 make -j5; CONF=android-arm64 make clean; lib/armeabi-v7a/libdrawterm.so: CONF=android-arm make -j5; CONF=android-arm make clean; lib/x86/libdrawterm.so: CONF=android-386 make -j5; CONF=android-386 make clean; lib/x86_64/libdrawterm.so: CONF=android-amd64 make -j5; CONF=android-amd64 make clean; drawterm.apk: drawterm-signed.apk $(SDKPREFIX)/build-tools/30.0.3/zipalign -v -f 4 $< $@ drawterm-signed.apk: drawterm-unsigned.apk drawterm.keystore $(JAVA_HOME)/bin/jarsigner -verbose -keystore ./drawterm.keystore -storepass glendarocks -keypass glendarocks -signedjar $@ $< drawtermKey drawterm-unsigned.apk: $(OBJS) $(SDKPREFIX)/build-tools/30.0.3/aapt package -v -f -M gui-android/AndroidManifest.xml -S gui-android/res -I $(SDKPREFIX)/platforms/android-21/android.jar -F $@ gui-android/bin $(SDKPREFIX)/build-tools/30.0.3/aapt add $@ $(OBJS) drawterm.keystore: $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=9front,O=Android,C=US" -keystore $@ -storepass glendarocks -keypass glendarocks -alias drawtermKey -keyalg RSA -v drawterm-9front-0~git20220608.bee4db6/Make.android-386000066400000000000000000000012301424653647700217720ustar00rootroot00000000000000# Android SDKPREFIX=$(HOME)/Android/Sdk NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin JAVA_HOME=/usr PTHREAD=-pthread AR=$(NDKPREFIX)/i686-linux-android-ar AS=$(NDKPREFIX)/i686-linux-android-as RANLIB=$(NDKPREFIX)/i686-linux-android-ranlib STRIP=$(NDKPREFIX)/i686-linux-android-strip CC=$(NDKPREFIX)/i686-linux-android21-clang CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC O=o OS=posix GUI=android LDADD=-ggdb -lm -shared -llog -landroid LDFLAGS=$(PTHREAD) TARG=lib/x86/libdrawterm.so AUDIO=none all: default libmachdep.a: arch=386; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.android-amd64000066400000000000000000000012471424653647700223750ustar00rootroot00000000000000# Android SDKPREFIX=$(HOME)/Android/Sdk NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin JAVA_HOME=/usr PTHREAD=-pthread AR=$(NDKPREFIX)/x86_64-linux-android-ar AS=$(NDKPREFIX)/x86_64-linux-android-as RANLIB=$(NDKPREFIX)/x86_64-linux-android-ranlib STRIP=$(NDKPREFIX)/x86_64-linux-android-strip CC=$(NDKPREFIX)/x86_64-linux-android21-clang CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC O=o OS=posix GUI=android LDADD=-ggdb -lm -shared -llog -landroid LDFLAGS=$(PTHREAD) TARG=lib/x86_64/libdrawterm.so AUDIO=none all: default libmachdep.a: arch=amd64; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.android-arm000066400000000000000000000012621424653647700222360ustar00rootroot00000000000000# Android SDKPREFIX=$(HOME)/Android/Sdk NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin JAVA_HOME=/usr PTHREAD=-pthread AR=$(NDKPREFIX)/arm-linux-androideabi-ar AS=$(NDKPREFIX)/arm-linux-androideabi-as RANLIB=$(NDKPREFIX)/arm-linux-androideabi-ranlib STRIP=$(NDKPREFIX)/arm-linux-androideabi-strip CC=$(NDKPREFIX)/armv7a-linux-androideabi21-clang CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC O=o OS=posix GUI=android LDADD=-ggdb -lm -shared -llog -landroid LDFLAGS=$(PTHREAD) TARG=lib/armeabi-v7a/libdrawterm.so AUDIO=none all: default libmachdep.a: arch=arm; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.android-arm64000066400000000000000000000012571424653647700224140ustar00rootroot00000000000000# Android SDKPREFIX=$(HOME)/Android/Sdk NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin JAVA_HOME=/usr PTHREAD=-pthread AR=$(NDKPREFIX)/aarch64-linux-android-ar AS=$(NDKPREFIX)/aarch64-linux-android-as RANLIB=$(NDKPREFIX)/aarch64-linux-android-ranlib STRIP=$(NDKPREFIX)/aarch64-linux-android-strip CC=$(NDKPREFIX)/aarch64-linux-android21-clang CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC O=o OS=posix GUI=android LDADD=-ggdb -lm -shared -llog -landroid LDFLAGS=$(PTHREAD) TARG=lib/arm64-v8a/libdrawterm.so AUDIO=none all: default libmachdep.a: arch=arm64; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.config000066400000000000000000000000501424653647700213000ustar00rootroot00000000000000AUDIO=none include $(ROOT)/Make.$(CONF) drawterm-9front-0~git20220608.bee4db6/Make.dragonfly000066400000000000000000000007141424653647700220270ustar00rootroot00000000000000# DragonFlyBSD PTHREAD=-pthread AR=ar AS=as RANLIB=ranlib X11=/usr/local CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib64 -L$(X11)/lib -lX11 -ggdb LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=none all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.fbdev000066400000000000000000000007301424653647700211260ustar00rootroot00000000000000# Unix #PTHREAD= # for Mac PTHREAD=-pthread AR=ar AS=as RANLIB=ranlib CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=fbdev LDADD=-ggdb -lm -lasound LDFLAGS=$(PTHREAD) TARG=drawterm # AUDIO=none AUDIO=alsa all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/; s/armv[567].*/arm/; s/aarch64/arm64/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.freebsd000066400000000000000000000007111424653647700214510ustar00rootroot00000000000000# OpenBSD PTHREAD=-pthread AR=ar AS=as RANLIB=ranlib X11=/usr/local CC=clang CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib64 -L$(X11)/lib -lX11 -ggdb LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=unix all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.irix000066400000000000000000000007551424653647700210220ustar00rootroot00000000000000# Unix PTHREAD= # for Mac #PTHREAD=-pthread AR=ar AS=as ASFLAGS=-c -mips3 RANLIB=true X11=/usr/X11R6 #CC=gcc #CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 CC=cc CFLAGS=-g -O2 -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -DIRIX O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib -lX11 -g -lpthread LDFLAGS=$(PTHREAD) TARG=drawterm MAKE=gmake all: default libmachdep.a: (cd posix-mips && $(MAKE)) drawterm-9front-0~git20220608.bee4db6/Make.linux386000066400000000000000000000006221424653647700214400ustar00rootroot00000000000000# Unix PTHREAD=-pthread AR=ar AS=as RANLIB=ranlib X11=/usr/X11R6 CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib64 -L$(X11)/lib -lX11 -ggdb -lm LDFLAGS=$(PTHREAD) TARG=drawterm # AUDIO=none AUDIO=unix all: default libmachdep.a: arch=386; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.netbsd000066400000000000000000000010001424653647700213060ustar00rootroot00000000000000# NetBSD PTHREAD=-pthread AR=ar AS=as RANLIB=ranlib X11=/usr/X11R7 CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-Wl,-rpath,$(X11)/lib64 -Wl,-rpath,$(X11)/lib -L$(X11)/lib64 -L$(X11)/lib -lX11 -ggdb -lossaudio LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=unix all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.openbsd000066400000000000000000000007441424653647700214770ustar00rootroot00000000000000# OpenBSD PTHREAD=-pthread AR=ar AS=as RANLIB=ranlib X11=/usr/X11R6 CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib64 -L$(X11)/lib -lX11 -lsndio -ggdb LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=sndio all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/; s/macppc/power/; s/socppc/power/; s/x86_64/amd64/; s/sparc64/sun4u/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.osx000066400000000000000000000006361424653647700206560ustar00rootroot00000000000000# Mac OS X PTHREAD= # for Mac AR=ar AS=as RANLIB=ranlib CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=osx LDADD=-ggdb -framework Carbon -framework QuickTime LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=none all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.osx-cocoa000066400000000000000000000006241424653647700217350ustar00rootroot00000000000000# Mac OS X PTHREAD= # for Mac AR=ar AS=as RANLIB=ranlib CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=cocoa LDADD=-ggdb -framework AppKit -framework OpenGL LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=none all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/x86_64/amd64/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.osx-x11000066400000000000000000000006731424653647700212660ustar00rootroot00000000000000# Mac OS X PTHREAD= # for Mac AR=ar AS=as RANLIB=ranlib X11=/usr/X11R6 CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib -lX11 -ggdb LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=none all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.pthread000066400000000000000000000006451424653647700214740ustar00rootroot00000000000000# Unix #PTHREAD= # for Mac PTHREAD=-pthread -DPTHREAD AR=ar AS=no-as-here RANLIB=ranlib X11=/usr/X11R6 CC=gcc CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib64 -L$(X11)/lib -lX11 -ggdb LDFLAGS=$(PTHREAD) TARG=drawterm # AUDIO=none AUDIO=unix all: default libmachdep.a: (cd posix-port && make) drawterm-9front-0~git20220608.bee4db6/Make.sun000066400000000000000000000005711424653647700206500ustar00rootroot00000000000000# Sun-specific PTHREAD= AR=ar AS=as RANLIB=ranlib X11=/usr/X11R6 CC=cc CFLAGS=-xCC -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -g -D_THREAD_SAFE O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib -lX11 -lrt -lpthread -lsocket -lnsl LDFLAGS= TARG=drawterm AUDIO=none all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.unix000066400000000000000000000010401424653647700210160ustar00rootroot00000000000000# Unix #PTHREAD= # for Mac PTHREAD=-pthread AR=ar AS=as RANLIB=ranlib X11=/usr/X11R6 CC=gcc CFLAGS=-Wall -Wno-missing-braces -Wno-parentheses -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix GUI=x11 LDADD=-L$(X11)/lib64 -L$(X11)/lib -lX11 -ggdb -lm LDFLAGS=$(PTHREAD) TARG=drawterm # AUDIO=none AUDIO=unix all: default libmachdep.a: arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/; s/x86_64/amd64/; s/armv[567].*/arm/; s/aarch64/arm64/'`; \ (cd posix-$$arch && make) drawterm-9front-0~git20220608.bee4db6/Make.win32000066400000000000000000000015271424653647700210070ustar00rootroot00000000000000# Windows via mingw32 # MING=mingw32- is necessary if you're cross-compiling # on another platform. Otherwise the binaries are just # named gcc, etc. AUDIO=win32 MING=i686-w64-mingw32- #MING= AR=$(MING)ar CC=$(MING)gcc AS=$(MING)as RANLIB=$(MING)ranlib WINDRES=$(MING)windres CFLAGS=-Wall -Wno-missing-braces -I$(ROOT)/include -I$(ROOT) -I$(ROOT)/kern -c -D_X86_ -DIS_32 -DWINDOWS -DUNICODE -O2 O=o FS=fs-win32 IP=win32 OS=win32 GUI=win32 LDADD=-lkernel32 -ladvapi32 -lgdi32 -lmpr -lwsock32 -lws2_32 -lmsvcrt -lmingw32 -lwinmm TARG=drawterm.exe XOFILES=glenda-t.$O # Windows via MSVC #AR=??? #CC=cl #CFLAGS=-c -nologo -W3 -YX -Zi -MT -Zl -Iinclude -DWINDOWS #O=obj #FS=fs-win32 #IP=win32 #OS=win32 #GUI=win32 all: default # for root libmachdep.a: (cd win32-386; make) glenda-t.$O: glenda-t.rc glenda-t.ico $(WINDRES) -i glenda-t.rc -o glenda-t.o drawterm-9front-0~git20220608.bee4db6/Make.win64000066400000000000000000000012151424653647700210060ustar00rootroot00000000000000# Windows via mingw-w64 # MING=mingw32- is necessary if you're cross-compiling # on another platform. Otherwise the binaries are just # named gcc, etc. AUDIO=win32 MING=x86_64-w64-mingw32- #MING= AR=$(MING)ar CC=$(MING)gcc AS=$(MING)as RANLIB=$(MING)ranlib WINDRES=$(MING)windres CFLAGS=-Wall -Wno-missing-braces -I$(ROOT)/include -I$(ROOT) -I$(ROOT)/kern -c -DWINDOWS -DUNICODE -O2 O=o FS=fs-win32 IP=win32 OS=win32 GUI=win32 LDADD=-lgdi32 -lws2_32 -lwinmm -mwindows TARG=drawterm.exe XOFILES=glenda-t.$O all: default # for root libmachdep.a: (cd posix-amd64; make) glenda-t.$O: glenda-t.rc glenda-t.ico $(WINDRES) -i glenda-t.rc -o glenda-t.o drawterm-9front-0~git20220608.bee4db6/Makefile000066400000000000000000000022101424653647700206740ustar00rootroot00000000000000ROOT=. include Make.config OFILES=\ main.$O\ cpu.$O\ aan.$O\ secstore.$O\ latin1.$O\ $(OS)-factotum.$O\ $(XOFILES)\ LIBS1=\ kern/libkern.a\ exportfs/libexportfs.a\ libauth/libauth.a\ libauthsrv/libauthsrv.a\ libsec/libsec.a\ libmp/libmp.a\ libmemdraw/libmemdraw.a\ libmemlayer/libmemlayer.a\ libdraw/libdraw.a\ gui-$(GUI)/libgui.a\ libc/libc.a\ libip/libip.a\ # stupid gcc LIBS=$(LIBS1) $(LIBS1) $(LIBS1) libmachdep.a default: $(TARG) $(TARG): $(OFILES) $(LIBS) $(CC) $(LDFLAGS) -o $(TARG) $(OFILES) $(LIBS) $(LDADD) %.$O: %.c $(CC) $(CFLAGS) $*.c clean: rm -f *.o */*.o */*.a *.a drawterm drawterm.exe kern/libkern.a: (cd kern; $(MAKE)) exportfs/libexportfs.a: (cd exportfs; $(MAKE)) libauth/libauth.a: (cd libauth; $(MAKE)) libauthsrv/libauthsrv.a: (cd libauthsrv; $(MAKE)) libmp/libmp.a: (cd libmp; $(MAKE)) libsec/libsec.a: (cd libsec; $(MAKE)) libmemdraw/libmemdraw.a: (cd libmemdraw; $(MAKE)) libmemlayer/libmemlayer.a: (cd libmemlayer; $(MAKE)) libdraw/libdraw.a: (cd libdraw; $(MAKE)) libc/libc.a: (cd libc; $(MAKE)) libip/libip.a: (cd libip; $(MAKE)) gui-$(GUI)/libgui.a: (cd gui-$(GUI); $(MAKE)) drawterm-9front-0~git20220608.bee4db6/README000066400000000000000000000022631424653647700201240ustar00rootroot00000000000000DESCRIPTION ----------- This is a fork of Russ Cox's drawterm to incorporate features from Plan9front (http://9front.org), most importantly DP9IK authentication support (see authsrv(6)) and the TLS based rcpu(1) protocol. INSTALLATION -------------- To build on Unix, run CONF=unix make. To build on Solaris using Sun cc, run CONF=sun make. To build on Windows, you can't use Visual C. Use Mingw on cygwin. To build on Mac OS X with X11 (xquartz), run CONF=osx-x11 make. To build on Mac OS X with Cocoa, run CONF=osx-cocoa make and "cp drawterm gui-cocoa/drawterm.app/". To build for Android, make sure Make.android* and gui-android/Makefile are correct for your build and target systems, then run make -f Make.android USAGE ------- On Android the five checkboxes at the top represent the three mouse buttons and mousewheel, determining which "buttons" are clicked. The "kb" button toggles the soft keyboard. CAVEATS -------- Be aware that right now on Android the login details are saved as a plaintext string if saved, and there is no secstore support. BINARIES --------- http://drawterm.9front.org/ SOURCE ------ http://git.9front.org/plan9front/drawterm/HEAD/info.html HELP ---- No. drawterm-9front-0~git20220608.bee4db6/aan.c000066400000000000000000000067341424653647700201560ustar00rootroot00000000000000#include #include #include enum { Hdrsz = 3*4, Bufsize = 8*1024, }; typedef struct Hdr Hdr; typedef struct Buf Buf; typedef struct Client Client; struct Hdr { uchar nb[4]; // Number of data bytes in this message uchar msg[4]; // Message number uchar acked[4]; // Number of messages acked }; struct Buf { Hdr hdr; uchar buf[Bufsize]; Buf *next; }; struct Client { QLock lk; char *addr; int netfd; int pipefd; int timeout; int reader; int writer; int syncer; ulong inmsg; ulong outmsg; Buf *unackedhead; Buf **unackedtail; }; static void reconnect(Client *c) { Buf *b; int n; ulong to; qlock(&c->lk); to = (ulong)time(0) + c->timeout; Again: for(;;){ if(c->netfd >= 0){ close(c->netfd); c->netfd = -1; } if((c->netfd = dial(c->addr,nil,nil,nil)) >= 0) break; if((ulong)time(0) >= to) sysfatal("dial timed out: %r"); sleep(1000); } for(b = c->unackedhead; b != nil; b = b->next){ n = GBIT32(b->hdr.nb); PBIT32(b->hdr.acked, c->inmsg); if(write(c->netfd, &b->hdr, Hdrsz) != Hdrsz || write(c->netfd, b->buf, n) != n){ print("write error: %r\n"); goto Again; } } qunlock(&c->lk); } static void aanwriter(void *arg) { Client *c = (Client*)arg; Buf *b; int n; ulong m; for(;;){ b = malloc(sizeof(Buf)); if(b == nil) break; if((n = read(c->pipefd, b->buf, Bufsize)) < 0){ free(b); break; } qlock(&c->lk); m = c->outmsg++; PBIT32(b->hdr.nb, n); PBIT32(b->hdr.msg, m); PBIT32(b->hdr.acked, c->inmsg); b->next = nil; if(c->unackedhead == nil) c->unackedtail = &c->unackedhead; *c->unackedtail = b; c->unackedtail = &b->next; if(c->netfd < 0 || write(c->netfd, &b->hdr, Hdrsz) != Hdrsz || write(c->netfd, b->buf, n) != n){ qunlock(&c->lk); continue; } qunlock(&c->lk); if(n == 0) break; } close(c->pipefd); c->pipefd = -1; } static void aansyncer(void *arg) { Client *c = (Client*)arg; Hdr hdr; for(;;){ sleep(4000); qlock(&c->lk); if(c->netfd >= 0){ PBIT32(hdr.nb, 0); PBIT32(hdr.acked, c->inmsg); PBIT32(hdr.msg, -1); write(c->netfd, &hdr, Hdrsz); } qunlock(&c->lk); } } static void aanreader(void *arg) { Client *c = (Client*)arg; ulong a, m, lastacked = 0; Buf *b, *x; int n; Restart: b = mallocz(sizeof(Buf), 1); for(;;){ if(readn(c->netfd, &b->hdr, Hdrsz) != Hdrsz) break; a = GBIT32(b->hdr.acked); m = GBIT32(b->hdr.msg); n = GBIT32(b->hdr.nb); if(n == 0){ if(m == (ulong)-1) continue; goto Closed; } else if(n < 0 || n > Bufsize) goto Closed; if(readn(c->netfd, b->buf, n) != n) break; if(m != c->inmsg) continue; c->inmsg++; if((long)(a - lastacked) > 0){ qlock(&c->lk); while((x = c->unackedhead) != nil){ assert(GBIT32(x->hdr.msg) == lastacked); c->unackedhead = x->next; free(x); if(++lastacked == a) break; } qunlock(&c->lk); } if(c->pipefd < 0) goto Closed; write(c->pipefd, b->buf, n); } free(b); reconnect(c); goto Restart; Closed: free(b); if(c->pipefd >= 0) write(c->pipefd, "", 0); } int aanclient(char *addr, int timeout) { Client *c; int pfd[2]; if(pipe(pfd) < 0) sysfatal("pipe: %r"); c = mallocz(sizeof(Client), 1); c->addr = addr; c->netfd = -1; c->pipefd = pfd[1]; c->inmsg = 0; c->outmsg = 0; c->timeout = 60; reconnect(c); c->timeout = timeout; c->writer = kproc("aanwriter", aanwriter, c); c->reader = kproc("aanreader", aanreader, c); c->syncer = kproc("aansyncer", aansyncer, c); return pfd[0]; } drawterm-9front-0~git20220608.bee4db6/args.h000066400000000000000000000013051424653647700203450ustar00rootroot00000000000000extern char *argv0; #define ARGBEGIN for((argv0? 0: (argv0=*argv)),argv++,argc--;\ argv[0] && argv[0][0]=='-' && argv[0][1];\ argc--, argv++) {\ char *_args, *_argt;\ Rune _argc;\ _args = &argv[0][1];\ if(_args[0]=='-' && _args[1]==0){\ argc--; argv++; break;\ }\ _argc = 0;\ while(*_args && (_args += chartorune(&_argc, _args)))\ switch(_argc) #define ARGEND SET(_argt);USED(_argt); USED(_argc); USED(_args);}USED(argv); USED(argc); #define ARGF() (_argt=_args, _args="",\ (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) #define ARGC() _argc #define EARGF(x) (_argt=_args, _args="",\ (*_argt? _argt: argv[1]? (argc--, *++argv): (x, (char*)0))) drawterm-9front-0~git20220608.bee4db6/cpu.c000066400000000000000000000462351424653647700202060ustar00rootroot00000000000000/* * cpu.c - Make a connection to a cpu server */ #include #include #include #include #include #include #include "args.h" #include "drawterm.h" #define MaxStr 128 static void usage(void); static void writestr(int, char*, char*, int); static int readstr(int, char*, int); static char *keyspec = ""; static AuthInfo *p9any(int); static int getkey(Authkey*, char*, char*, char*, char*); static int findkey(Authkey*, char*, char*, char*); static char *host; static int aanfilter; static int aanto = 3600 * 24; static int norcpu; static int nokbd; static int nogfx; static char *ealgs = "rc4_256 sha1"; /* authentication mechanisms */ static int p9authssl(int); static int p9authtls(int); char *authserver; char *secstore; char *user, *pass; char secstorebuf[65536]; char *geometry; extern void guimain(void); char* estrdup(char *s) { s = strdup(s); if(s == nil) sysfatal("out of memory"); return s; } static void ending(void) { panic("ending"); } int mountfactotum(void) { int fd; if((fd = dialfactotum()) < 0) return -1; if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0){ fprint(2, "mount factotum: %r\n"); return -1; } if((fd = open("/mnt/factotum/ctl", OREAD)) < 0){ fprint(2, "open /mnt/factotum/ctl: %r\n"); return -1; } close(fd); return 0; } static int startaan(char *host, int fd) { static char script[] = "~ $#netdir 1 || netdir=/net/tcp/clone\n" "netdir=`{basename -d $netdir} || exit\n" "<>$netdir/clone {\n" " netdir=$netdir/`{read} || exit\n" " >[3] $netdir/ctl {\n" " echo -n 'announce *!0' >[1=3]\n" " echo `{cat $netdir/local} || exit\n" " bind '#|' /mnt/aan || exit\n" " exec aan -m $aanto $netdir <>/mnt/aan/data1 >[1=0] >[2]/dev/null &\n" " }\n" "}\n" "<>/mnt/aan/data >[1=0] >[2]/dev/null {\n" " rfork n\n" " fn server {\n" " echo -n aanserver $netdir >/proc/$pid/args\n" " rm -f /env/^('fn#server' aanto)\n" " . <{n=`{read} && ! ~ $#n 0 && read -c $n} >[2=1]\n" " }\n" " exec tlssrv -A /bin/rc -c server\n" " exit\n" "}\n"; char buf[128], *p, *na; int n; snprint(buf, sizeof buf, "aanto=%d\n", aanto); if(fprint(fd, "%7ld\n%s%s", strlen(buf)+strlen(script), buf, script) < 0) sysfatal("sending aan script: %r"); n = read(fd, buf, sizeof(buf)-1); close(fd); while(n > 0 && buf[n-1] == '\n') n--; if(n <= 0) return -1; buf[n] = 0; if((p = strrchr(buf, '!')) != nil) na = strdup(netmkaddr(host, "tcp", p+1)); else na = strdup(buf); return aanclient(na, aanto); } static void rcpuexit(void) { char *s = getenv("rstatus"); if(s != nil) exit(*s); } void rcpu(char *host, char *cmd) { static char script[] = "syscall fversion 0 65536 buf 256 >/dev/null >[2=1]\n" "mount -nc /fd/0 /mnt/term || exit\n" "bind -q /mnt/term/dev/cons /dev/cons\n" "if(test -r /mnt/term/dev/kbd){\n" " /dev/cons >[2=1] aux/kbdfs -dq -m /mnt/term/dev\n" " bind -q /mnt/term/dev/cons /dev/cons\n" "}\n" "/dev/cons >[2=1] service=cpu %s\n" "echo -n $status >/mnt/term/env/rstatus >[2]/dev/null\n" "echo -n hangup >/proc/$pid/notepg\n"; int fd; if((fd = dial(netmkaddr(host, "tcp", "rcpu"), nil, nil, nil)) < 0) return; /* provide /dev/kbd for kbdfs */ if(!nokbd) bind("#b", "/dev", MAFTER); fd = p9authtls(fd); if(aanfilter){ fd = startaan(host, fd); if(fd < 0) sysfatal("startaan: %r"); fd = p9authtls(fd); } memset(secstorebuf, 0, sizeof(secstorebuf)); /* forget secstore secrets */ if(cmd == nil) cmd = smprint(script, "rc -li"); else { char *run = smprint("rc -lc %q", cmd); cmd = smprint(script, run); free(run); } if(fprint(fd, "%7ld\n%s", strlen(cmd), cmd) < 0) sysfatal("sending script: %r"); free(cmd); /* /env/rstatus is written by the remote script to communicate exit status */ remove("/env/rstatus"); atexit(rcpuexit); /* Begin serving the namespace */ exportfs(fd); } void ncpu(char *host, char *cmd) { char buf[MaxStr]; int fd; if((fd = dial(netmkaddr(host, "tcp", "ncpu"), nil, nil, nil)) < 0) return; /* negotiate authentication mechanism */ strcpy(buf, "p9"); if(ealgs != nil){ strcat(buf, " "); strcat(buf, ealgs); } writestr(fd, buf, "negotiating authentication method", 0); if(readstr(fd, buf, sizeof buf) < 0) sysfatal("can't negotiate authentication method: %r"); if(*buf) sysfatal("%s", buf); /* authenticate and encrypt the channel */ fd = p9authssl(fd); /* tell remote side the command */ if(cmd != nil){ cmd = smprint("!%s", cmd); writestr(fd, cmd, "cmd", 0); free(cmd); } /* Tell the remote side where our working directory is */ if(getcwd(buf, sizeof(buf)) == 0) writestr(fd, "NO", "dir", 0); else writestr(fd, buf, "dir", 0); /* * Wait for the other end to execute and start our file service * of /mnt/term */ if(readstr(fd, buf, sizeof(buf)) < 0) sysfatal("waiting for FS: %r"); if(strncmp("FS", buf, 2) != 0) { print("remote cpu: %s", buf); exits(buf); } if(readstr(fd, buf, sizeof(buf)) < 0) sysfatal("waiting for remote export: %r"); if(strcmp(buf, "/") != 0){ print("remote cpu: %s", buf); exits(buf); } write(fd, "OK", 2); /* Begin serving the gnot namespace */ exportfs(fd); } void usage(void) { fprint(2, "usage: %s [-GBO] " "[-h host] [-u user] [-a authserver] [-s secstore] " "[-e 'crypt hash'] [-k keypattern] " "[-p] [-t timeout] " "[-r root] " "[-g geometry] " "[-c cmd ...]\n", argv0); exits("usage"); } static char *cmd; extern void cpubody(void); void cpumain(int argc, char **argv) { char *s; user = getenv("USER"); if((pass = getenv("PASS")) != nil) remove("/env/PASS"); host = getenv("cpu"); authserver = getenv("auth"); ARGBEGIN{ case 'G': nogfx = 1; /* wet floor */ case 'B': nokbd = 1; break; case 'O': norcpu = 1; break; case 'p': aanfilter = 1; break; case 't': aanto = (int)strtol(EARGF(usage()), nil, 0); break; case 'h': host = EARGF(usage()); break; case 'a': authserver = EARGF(usage()); break; case 's': secstore = EARGF(usage()); break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) ealgs = nil; break; case 'k': keyspec = EARGF(usage()); break; case 'u': user = EARGF(usage()); break; case 'r': s = smprint("/root/%s", EARGF(usage())); cleanname(s); if(bind(s, "/root", MREPL) < 0) panic("bind /root: %r"); free(s); break; case 'c': cmd = estrdup(EARGF(usage())); while((s = ARGF()) != nil){ char *old = cmd; cmd = smprint("%s %q", cmd, s); free(old); } break; case 'g': /* X11 geometry string [=][{xX}][{+-}{+-}] */ geometry = EARGF(usage()); break; default: usage(); }ARGEND; if(argc != 0) usage(); if(!nogfx) guimain(); else cpubody(); } void cpubody(void) { char *s; if(!nogfx){ if(bind("#i", "/dev", MBEFORE) < 0) panic("bind #i: %r"); if(bind("#m", "/dev", MBEFORE) < 0) panic("bind #m: %r"); if(cmd == nil) atexit(ending); } if(bind("/root", "/", MAFTER) < 0) panic("bind /root: %r"); if(host == nil) if((host = readcons("cpu", "cpu", 0)) == nil) sysfatal("user terminated input"); if(authserver == nil) if((authserver = readcons("auth", host, 0)) == nil) sysfatal("user terminated input"); if(user == nil) if((user = readcons("user", "glenda", 0)) == nil) sysfatal("user terminated input"); if(mountfactotum() < 0){ if(secstore == nil) secstore = authserver; if(havesecstore(secstore, user)){ s = secstorefetch(secstore, user, pass); if(s){ if(strlen(s) >= sizeof secstorebuf) sysfatal("secstore data too big"); strcpy(secstorebuf, s); } } } if(!norcpu) rcpu(host, cmd); ncpu(host, cmd); sysfatal("can't dial %s: %r", host); } void writestr(int fd, char *str, char *thing, int ignore) { int l, n; l = strlen(str); n = write(fd, str, l+1); if(!ignore && n < 0) sysfatal("writing network: %s: %r", thing); } int readstr(int fd, char *str, int len) { int n; while(len) { n = read(fd, str, 1); if(n < 0) return -1; if(n == 0){ werrstr("hung up"); return -1; } if(*str == '\0') return 0; str++; len--; } return -1; } static void mksecret(char *t, uchar *f) { sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); } /* * plan9 authentication followed by rc4 encryption */ static int p9authssl(int fd) { uchar key[16]; uchar digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; AuthInfo *ai; ai = p9any(fd); memset(secstorebuf, 0, sizeof(secstorebuf)); /* forget secstore secrets */ if(ai == nil) sysfatal("can't authenticate: %r"); if(ealgs == nil) return fd; if(ai->nsecret < 8){ sysfatal("p9authssl: secret too small"); return -1; } memmove(key+4, ai->secret, 8); /* exchange random numbers */ genrandom(key, 4); if(write(fd, key, 4) != 4){ sysfatal("p9authssl: write random: %r"); return -1; } if(readn(fd, key+12, 4) != 4){ sysfatal("p9authssl: read random: %r"); return -1; } /* scramble into two secrets */ sha1(key, sizeof(key), digest, nil); mksecret(fromclientsecret, digest); mksecret(fromserversecret, digest+10); /* set up encryption */ fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); if(fd < 0) sysfatal("p9authssl: pushssl: %r"); return fd; } /* * p9any authentication followed by tls-psk encryption */ static int p9authtls(int fd) { AuthInfo *ai; TLSconn *conn; ai = p9any(fd); if(ai == nil) sysfatal("can't authenticate: %r"); conn = mallocz(sizeof(TLSconn), 1); conn->pskID = "p9secret"; conn->psk = ai->secret; conn->psklen = ai->nsecret; fd = tlsClient(fd, conn); if(fd < 0) sysfatal("tlsClient: %r"); auth_freeAI(ai); free(conn->sessionID); free(conn); return fd; } int authdial(char *net, char *dom) { return dial(netmkaddr(authserver, "tcp", "ticket"), 0, 0, 0); } static int getastickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen) { int asfd, rv; char *dom; dom = tr->authdom; asfd = authdial(nil, dom); if(asfd < 0) return -1; if(y != nil){ PAKpriv p; rv = -1; tr->type = AuthPAK; if(_asrequest(asfd, tr) != 0 || write(asfd, y, PAKYLEN) != PAKYLEN) goto Out; authpak_new(&p, key, (uchar*)tbuf, 1); if(write(asfd, tbuf, PAKYLEN) != PAKYLEN) goto Out; if(_asrdresp(asfd, tbuf, 2*PAKYLEN) != 2*PAKYLEN) goto Out; memmove(y, tbuf, PAKYLEN); if(authpak_finish(&p, key, (uchar*)tbuf+PAKYLEN)) goto Out; } tr->type = AuthTreq; rv = _asgetticket(asfd, tr, tbuf, tbuflen); Out: close(asfd); return rv; } static int mkservertickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen) { Ticket t; int ret; if(strcmp(tr->authid, tr->hostid) != 0) return -1; memset(&t, 0, sizeof(t)); ret = 0; if(y != nil){ PAKpriv p; t.form = 1; memmove(tbuf, y, PAKYLEN); authpak_new(&p, key, y, 0); authpak_finish(&p, key, (uchar*)tbuf); } memmove(t.chal, tr->chal, CHALLEN); strcpy(t.cuid, tr->uid); strcpy(t.suid, tr->uid); genrandom((uchar*)t.key, sizeof(t.key)); t.num = AuthTc; ret += convT2M(&t, tbuf+ret, tbuflen-ret, key); t.num = AuthTs; ret += convT2M(&t, tbuf+ret, tbuflen-ret, key); memset(&t, 0, sizeof(t)); return ret; } static int gettickets(Authkey *key, Ticketreq *tr, uchar *y, char *tbuf, int tbuflen) { int ret; ret = getastickets(key, tr, y, tbuf, tbuflen); if(ret > 0) return ret; return mkservertickets(key, tr, y, tbuf, tbuflen); } /* * prompt user for a key. don't care about memory leaks, runs standalone */ static Attr* promptforkey(char *params) { char *v; int fd; Attr *a, *attr; char *def; fd = open("/dev/cons", ORDWR); if(fd < 0) sysfatal("opening /dev/cons: %r"); attr = _parseattr(params); fprint(fd, "\n!Adding key:"); for(a=attr; a; a=a->next) if(a->type != AttrQuery && a->name[0] != '!') fprint(fd, " %q=%q", a->name, a->val); fprint(fd, "\n"); for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]=='!') continue; def = nil; if(strcmp(v, "user") == 0) def = getuser(); a->val = readcons(v, def, 0); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } for(a=attr; a; a=a->next){ v = a->name; if(a->type != AttrQuery || v[0]!='!') continue; def = nil; if(strcmp(v+1, "user") == 0) def = getuser(); a->val = readcons(v+1, def, 1); if(a->val == nil) sysfatal("user terminated key input"); a->type = AttrNameval; } fprint(fd, "!\n"); close(fd); return attr; } /* * send a key to the mounted factotum */ static int sendkey(Attr *attr) { int fd, rv; char buf[1024]; fd = open("/mnt/factotum/ctl", ORDWR); if(fd < 0) sysfatal("opening /mnt/factotum/ctl: %r"); rv = fprint(fd, "key %A\n", attr); read(fd, buf, sizeof buf); close(fd); return rv; } int askuser(char *params) { Attr *attr; fmtinstall('A', _attrfmt); attr = promptforkey(params); if(attr == nil) sysfatal("no key supplied"); if(sendkey(attr) < 0) sysfatal("sending key to factotum: %r"); return 0; } AuthInfo* p9anyfactotum(int fd, int afd) { return auth_proxy(fd, askuser, "proto=p9any role=client %s", keyspec); } AuthInfo* p9any(int fd) { char buf[1024], buf2[1024], *bbuf, *p, *proto, *dom; uchar crand[2*NONCELEN], cchal[CHALLEN], y[PAKYLEN]; char tbuf[2*MAXTICKETLEN+MAXAUTHENTLEN+PAKYLEN], trbuf[TICKREQLEN+PAKYLEN]; Authkey authkey; Authenticator auth; int afd, i, n, m, v2, dp9ik; Ticketreq tr; Ticket t; AuthInfo *ai; if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0) return p9anyfactotum(fd, afd); werrstr(""); if(readstr(fd, buf, sizeof buf) < 0) sysfatal("cannot read p9any negotiation: %r"); bbuf = buf; v2 = 0; if(strncmp(buf, "v.2 ", 4) == 0){ v2 = 1; bbuf += 4; } dp9ik = 0; proto = nil; while(bbuf != nil){ if((p = strchr(bbuf, ' '))) *p++ = 0; if((dom = strchr(bbuf, '@')) == nil) sysfatal("bad p9any domain"); *dom++ = 0; if(strcmp(bbuf, "p9sk1") == 0 || strcmp(bbuf, "dp9ik") == 0){ proto = bbuf; if(strcmp(proto, "dp9ik") == 0){ dp9ik = 1; break; } } bbuf = p; } if(proto == nil) sysfatal("server did not offer p9sk1 or dp9ik"); proto = estrdup(proto); sprint(buf2, "%s %s", proto, dom); if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1) sysfatal("cannot write user/domain choice in p9any"); if(v2){ if(readstr(fd, buf, sizeof buf) < 0) sysfatal("cannot read OK in p9any: %r"); if(memcmp(buf, "OK\0", 3) != 0) sysfatal("did not get OK in p9any: got %s", buf); } genrandom(crand, 2*NONCELEN); genrandom(cchal, CHALLEN); if(write(fd, cchal, CHALLEN) != CHALLEN) sysfatal("cannot write p9sk1 challenge: %r"); n = TICKREQLEN; if(dp9ik) n += PAKYLEN; if(readn(fd, trbuf, n) != n || convM2TR(trbuf, TICKREQLEN, &tr) <= 0) sysfatal("cannot read ticket request in p9sk1: %r"); if(!findkey(&authkey, user, tr.authdom, proto)){ again: if(!getkey(&authkey, user, tr.authdom, proto, pass)) sysfatal("no password"); } strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, user); strecpy(tr.uid, tr.uid+sizeof tr.uid, user); if(dp9ik){ memmove(y, trbuf+TICKREQLEN, PAKYLEN); n = gettickets(&authkey, &tr, y, tbuf, sizeof(tbuf)); } else { n = gettickets(&authkey, &tr, nil, tbuf, sizeof(tbuf)); } if(n <= 0) sysfatal("cannot get auth tickets in p9sk1: %r"); m = convM2T(tbuf, n, &t, &authkey); if(m <= 0 || t.num != AuthTc){ print("?password mismatch with auth server\n"); if(pass != nil && *pass) sysfatal("wrong password"); goto again; } n -= m; memmove(tbuf, tbuf+m, n); if(dp9ik && write(fd, y, PAKYLEN) != PAKYLEN) sysfatal("cannot send authpak public key back: %r"); auth.num = AuthAc; memmove(auth.rand, crand, NONCELEN); memmove(auth.chal, tr.chal, CHALLEN); m = convA2M(&auth, tbuf+n, sizeof(tbuf)-n, &t); n += m; if(write(fd, tbuf, n) != n) sysfatal("cannot send ticket and authenticator back: %r"); if((n=readn(fd, tbuf, m)) != m || memcmp(tbuf, "cpu:", 4) == 0){ if(n <= 4) sysfatal("cannot read authenticator"); /* * didn't send back authenticator: * sent back fatal error message. */ memmove(buf, tbuf, n); i = readn(fd, buf+n, sizeof buf-n-1); if(i > 0) n += i; buf[n] = 0; sysfatal("server says: %s", buf); } if(convM2A(tbuf, n, &auth, &t) <= 0 || auth.num != AuthAs || tsmemcmp(auth.chal, cchal, CHALLEN) != 0){ print("?you and auth server agree about password.\n"); print("?server is confused.\n"); sysfatal("server lies"); } memmove(crand+NONCELEN, auth.rand, NONCELEN); // print("i am %s there.\n", t.suid); ai = mallocz(sizeof(AuthInfo), 1); ai->suid = estrdup(t.suid); ai->cuid = estrdup(t.cuid); if(dp9ik){ static char info[] = "Plan 9 session secret"; ai->nsecret = 256; ai->secret = mallocz(ai->nsecret, 1); hkdf_x( crand, 2*NONCELEN, (uchar*)info, sizeof(info)-1, (uchar*)t.key, NONCELEN, ai->secret, ai->nsecret, hmac_sha2_256, SHA2_256dlen); } else { ai->nsecret = 8; ai->secret = mallocz(ai->nsecret, 1); des56to64((uchar*)t.key, ai->secret); } memset(&t, 0, sizeof(t)); memset(&auth, 0, sizeof(auth)); memset(&authkey, 0, sizeof(authkey)); memset(cchal, 0, sizeof(cchal)); memset(crand, 0, sizeof(crand)); free(proto); return ai; } static int findkey(Authkey *key, char *user, char *dom, char *proto) { char buf[8192], *f[50], *p, *ep, *nextp, *hex, *pass, *id, *role; int nf, haveproto, havedom, i; for(p=secstorebuf; *p; p=nextp){ nextp = strchr(p, '\n'); if(nextp == nil){ ep = p+strlen(p); nextp = ""; }else{ ep = nextp++; } if(ep-p >= sizeof buf){ print("warning: skipping long line in secstore factotum file\n"); continue; } memmove(buf, p, ep-p); buf[ep-p] = 0; nf = tokenize(buf, f, nelem(f)); if(nf == 0 || strcmp(f[0], "key") != 0) continue; id = pass = hex = role = nil; havedom = haveproto = 0; for(i=1; iaes, AESKEYLEN, hex, strlen(hex)) != AESKEYLEN) continue; } else { if(dec16((uchar*)key->des, DESKEYLEN, hex, strlen(hex)) != DESKEYLEN) continue; } } else { passtokey(key, pass); } if(strcmp(proto, "dp9ik") == 0) authpak_hash(key, user); memset(buf, 0, sizeof buf); return 1; } memset(buf, 0, sizeof buf); return 0; } static int getkey(Authkey *key, char *user, char *dom, char *proto, char *pass) { char buf[1024]; if(pass != nil && *pass) pass = estrdup(pass); else { snprint(buf, sizeof buf, "%s@%s %s password", user, dom, proto); pass = readcons(buf, nil, 1); memset(buf, 0, sizeof buf); } if(pass != nil){ snprint(secstorebuf, sizeof(secstorebuf), "key proto=%q dom=%q user=%q !password=%q\n", proto, dom, user, pass); memset(pass, 0, strlen(pass)); free(pass); return findkey(key, user, dom, proto); } return 0; } drawterm-9front-0~git20220608.bee4db6/drawterm.1000066400000000000000000000130711424653647700211520ustar00rootroot00000000000000.TH DRAWTERM 1 .SH NAME drawterm \- connection to cpu, fs, and auth servers .SH SYNOPSIS .B drawterm [ .B -GBO ] [ .B -h .I host ] [ .B -u .I user ] [ .B -a .I authserver ] [ .B -s .I secstore ] [ .B -e \fR'\fIcrypt hash\fR' ] [ .B -k .I keypattern ] [ .B -p ] [ .B -t .I timeout ] [ .B -r .I root ] [ .B -g .I geometry ] [ .B -c .I cmd \fR...] .SH DESCRIPTION .I Drawterm is a client for connecting venerable systems to Plan 9 systems. The standard behavior with no options provided is to begin a graphical session which will prompt for a cpu server, auth server, and password. If $USER is not set, drawterm will prompt for a username as well. The goal of drawterm is to provide an abstraction layer from the client operating system to the desired Plan 9 system. Client-side devices that can be represented as filesystems will be and are served from the namespace drawterm operates in. Generally, this means that drawterm behaves like a Plan 9 kernel and will attempt to reconstruct a Plan 9 terminal-like experience from a non-Plan 9 system. .PP The options are: .PD .TP .B -G Start drawterm in text-only mode (no graphics). .TP .B -B Disable kbdfs. .TP .B -O Use the old .IR cpu (1) to connect to the cpu server rather than .IR rcpu (1)\fR. .TP .B -h \fIhost Connect to \fIhost\fR for cpu. .TP .B -u \fIuser Remote user id. .TP .B -a \fIauthserver Connect to \fIauthserver\fR for auth. .TP .B -s \fIsecstore Sets the address of the .IR secstore (8) server. If the -s option is absent, .IR secstore (1) will attempt to dial tcp!$auth!secstore (or the otherwise specified auth server). .TP .B -e \fR'\fIcrypt hash\fR' Specifies the \fR'\fIcrypt hash\fR' for the connection. The default is 'rc4_256 sha1'. Usage of no encryption can be specified by 'clear' as per .IR ssl (3)\fR. Note that this option is deprecated and only relevant to the outdated .IR cpu (1) protocol. .TP .B -k \fIkeypattern Use keypattern to select a key to authenticate to the remote side (see .IR auth (2)\fR). .TP .B -p Protect the connection against connection resets by establishing .IR aan (8) tunnel. .TP .B -t \fItimeout Set the timeout for .IR aan (8) to a value in .I seconds\fR (default is one day). .TP .B -r \fIroot Specifies the root directory on the client. The default is .I /root and all further paths are relative thereto. .TP .B -c \fIcmd \fR... The command to run can be passed with -c cmd ..., otherwise an interactive shell is started. The user's profile is run before the command with $service set to cpu to allow further customization of the environment (see .IR rc (1) for more information). .PP .SH ENVIRONMENT VARIABLES .IP USER Unless otherwise specified, the user stored in $USER is used for authentication. .IP PASS If $PASS is set, no password will be prompted for in authentication and the contents of $PASS will be used instead. .IP cpu Unless otherwise specified, the address stored in $cpu is used for the .IR rcpu (1) connection (if set). .IP auth Unless otherwise specified, the address stored in $auth is used for the .IR rcpu (1) connection (if set). .PP .SH SERVICES A number of services are provided in drawterm. The exact functionality and availability of certain features may be dependent on your platform or architecture: .TP .B /mnt/term A mount of the client machine's root filesystem as well as certain virtual filesystems to present Plan 9 devices and interfaces that are not available on non-Plan 9 systems. On Windows this is a directory containing the available lettered disks (C:, A:, etc.). Additionally, there is always a /mnt/term/root folder which is a copy of the client machine's namespace with no virtual filesystems present as to avoid conflicting names (such as with Linux's /root). .TP .B #b Assuming the -B flag is not set, /dev/kbd will be provided for kbdfs (see .IR kbd (3)\fR). .TP .B #i Assuming the -G flag is not set, various drawing device files will be provided in /dev (see .IR draw (3)\fR). .TP .B #m Assuming the -G flag is not set, files for controlling the mouse will provided in /dev (see .IR mouse (3)\fR). .TP .B #c A number of console device files giving access to the console screen and miscellaneous information are provided and mounted in /dev (see .IR cons (3)\fR). .TP .B #I The network filesystem is served and bound over /net, providing the interface to Internet Protocol stacks (see .IR ip (3)\fR). .TP .B #A An audio device filesystem is served, if possible, as a one-level directory in /dev (see .IR audio (3)\fR). Note that this device, if unable to be served, will not cause a panic in drawterm. .PP .SH EXAMPLES Make a headless rcpu session connecting to 10.30.167.25 using plan9.postnix.us as the auth server with .IR aan (8) enabled: .IP .EX drawterm -G -h 10.30.167.25 -a plan9.postnix.us -p .EE .PP Make a session using cpu rather than rcpu to tenshi.postnix.us; this command is the same for connecting to a Plan 9 4th edition system: .IP .EX drawterm -O -h tenshi.postnix.us .EE .PP .PP .SH SOURCE .B https://git.9front.org/plan9front/drawterm/HEAD/info.html .PP .SH "SEE ALSO" .IR rc (1), .IR cpu (1), .IR rcpu(1), .IR con (1), .IR import (4), .IR exportfs (4), .IR tlssrv (8), .IR aan (8) .PP .SH BUGS Drawterm is .I not a Plan 9 program. .PP .SH HISTORY Drawterm was originally developed by Russ Cox (rsc) for Plan 9 4th edition. This original version is still usable on Plan 9 and its forks which use the p9sk1 and older .IR authsrv (6) protocols. .B https://swtch.com/drawterm/ The 9front project has forked drawterm to incorporate features from 9front, most importantly dp9ik authentication support (see .IR authsrv (6)\fR) and the TLS-based .IR rcpu (1) protocol. drawterm-9front-0~git20220608.bee4db6/drawterm.h000066400000000000000000000005341424653647700212410ustar00rootroot00000000000000extern int havesecstore(char *addr, char *owner); extern char *secstore; extern char *secstorefetch(char *addr, char *owner, char *passwd); extern char *authserver; extern int exportfs(int); extern int dialfactotum(void); extern char *getuser(void); extern void cpumain(int, char**); extern char *estrdup(char*); extern int aanclient(char*, int); drawterm-9front-0~git20220608.bee4db6/drawterm.rc000066400000000000000000000032611424653647700214160ustar00rootroot00000000000000//Microsoft Developer Studio generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON1 ICON DISCARDABLE "glenda-t.ico" #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED drawterm-9front-0~git20220608.bee4db6/drawterm.res000066400000000000000000000033341424653647700216040ustar00rootroot00000000000000 h 0 (0`"""333DDDUUUfffwwwܺU˗uUDfTiݹuTVVtV|˨SFX̨JʇeCGݸjۋZ݆ffhi[wˈuJXܦ[YYYiGweۆݦhܖۇzݦݸXݦWܷwݶ݆xݖݕ}܇dLۈًwHيۼȜݹDݷ۷|ݗۻݗ{ܘݘݬݘ܊(ݙzݙ݈݉܊gڊxȜNjiܘݘʉۛQ)˙ɽ"}˘A&ͩʙʵ$ۛ2ݻj͸wʽډr|jڛ˨Uݺۊxw˻ۗxɊݘܫ e0 00hdrawterm-9front-0~git20220608.bee4db6/exportfs/000077500000000000000000000000001424653647700211135ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/exportfs/Makefile000066400000000000000000000003101424653647700225450ustar00rootroot00000000000000ROOT=.. include ../Make.config LIB=libexportfs.a OFILES=\ exportfs.$O\ exportsrv.$O default: $(LIB) $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) %.$O: %.c $(CC) $(CFLAGS) $*.c drawterm-9front-0~git20220608.bee4db6/exportfs/exportfs.c000066400000000000000000000202471424653647700231360ustar00rootroot00000000000000/* * exportfs - Export a plan 9 name space across a network */ #include #include #include #include #include "drawterm.h" #define Extern #include "exportfs.h" /* #define QIDPATH ((1LL<<48)-1) */ #define QIDPATH ((((vlong)1)<<48)-1) vlong newqid = 0; void (*fcalls[256])(Fsrpc*); /* accounting and debugging counters */ int filecnt; int freecnt; int qidcnt; int qfreecnt; int ncollision; int netfd; int exportfs(int fd) { char buf[ERRMAX], ebuf[ERRMAX]; Fsrpc *r; int i, n; fcalls[Tversion] = Xversion; fcalls[Tauth] = Xauth; fcalls[Tflush] = Xflush; fcalls[Tattach] = Xattach; fcalls[Twalk] = Xwalk; fcalls[Topen] = slave; fcalls[Tcreate] = Xcreate; fcalls[Tclunk] = Xclunk; fcalls[Tread] = slave; fcalls[Twrite] = slave; fcalls[Tremove] = Xremove; fcalls[Tstat] = Xstat; fcalls[Twstat] = Xwstat; srvfd = -1; netfd = fd; //dbg = 1; strcpy(buf, "this is buf"); strcpy(ebuf, "this is ebuf"); DEBUG(DFD, "exportfs: started\n"); // rfork(RFNOTEG); messagesize = iounit(netfd); if(messagesize == 0) messagesize = 8192+IOHDRSZ; Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs); // for(i=0; ibuf, messagesize); if(n <= 0) fatal(nil); if(convM2S(r->buf, n, &r->work) == 0){ iprint("convM2S %d byte message\n", n); for(i=0; ibuf[i]); if(i%16 == 15) iprint("\n"); } if(i%16) iprint("\n"); fatal("convM2S format error"); } if(0) iprint("<- %F\n", &r->work); DEBUG(DFD, "%F\n", &r->work); (fcalls[r->work.type])(r); } } void reply(Fcall *r, Fcall *t, char *err) { uchar *data; int m, n; t->tag = r->tag; t->fid = r->fid; if(err) { t->type = Rerror; t->ename = err; } else t->type = r->type + 1; if(0) iprint("-> %F\n", t); DEBUG(DFD, "\t%F\n", t); data = malloc(messagesize); /* not mallocz; no need to clear */ if(data == nil) fatal(Enomem); n = convS2M(t, data, messagesize); if((m=write(netfd, data, n))!=n){ iprint("wrote %d got %d (%r)\n", n, m); fatal("write"); } free(data); } Fid * getfid(int nr) { Fid *f; for(f = fidhash(nr); f; f = f->next) if(f->nr == nr) return f; return 0; } int freefid(int nr) { Fid *f, **l; char buf[128]; l = &fidhash(nr); for(f = *l; f; f = f->next) { if(f->nr == nr) { if(f->mid) { sprint(buf, "/mnt/exportfs/%d", f->mid); unmount(0, buf); psmap[f->mid] = 0; } if(f->f) { freefile(f->f); f->f = nil; } *l = f->next; f->next = fidfree; fidfree = f; return 1; } l = &f->next; } return 0; } Fid * newfid(int nr) { Fid *new, **l; int i; l = &fidhash(nr); for(new = *l; new; new = new->next) if(new->nr == nr) return 0; if(fidfree == 0) { fidfree = emallocz(sizeof(Fid) * Fidchunk); for(i = 0; i < Fidchunk-1; i++) fidfree[i].next = &fidfree[i+1]; fidfree[Fidchunk-1].next = 0; } new = fidfree; fidfree = new->next; memset(new, 0, sizeof(Fid)); new->next = *l; *l = new; new->nr = nr; new->fid = -1; new->mid = 0; return new; } Fsrpc * getsbuf(void) { static int ap; int look, rounds; Fsrpc *wb; int small_instead_of_fast = 1; if(small_instead_of_fast) ap = 0; /* so we always start looking at the beginning and reuse buffers */ for(rounds = 0; rounds < 10; rounds++) { for(look = 0; look < Nr_workbufs; look++) { if(++ap == Nr_workbufs) ap = 0; if(Workq[ap].busy == 0) break; } if(look == Nr_workbufs){ sleep(10 * rounds); continue; } wb = &Workq[ap]; wb->pid = 0; wb->canint = 0; wb->flushtag = NOTAG; wb->busy = 1; if(wb->buf == nil) /* allocate buffers dynamically to keep size down */ wb->buf = emallocz(messagesize); return wb; } fatal("No more work buffers"); return nil; } void freefile(File *f) { File *parent, *child; Loop: f->ref--; if(f->ref > 0) return; freecnt++; if(f->ref < 0) abort(); DEBUG(DFD, "free %s\n", f->name); /* delete from parent */ parent = f->parent; if(parent->child == f) parent->child = f->childlist; else{ for(child=parent->child; child->childlist!=f; child=child->childlist) if(child->childlist == nil) fatal("bad child list"); child->childlist = f->childlist; } freeqid(f->qidt); free(f->name); f->name = nil; free(f); f = parent; if(f != nil) goto Loop; } File * file(File *parent, char *name) { Dir *dir; char *path; File *f; DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name); path = makepath(parent, name); dir = dirstat(path); free(path); if(dir == nil) return nil; for(f = parent->child; f; f = f->childlist) if(strcmp(name, f->name) == 0) break; if(f == nil){ f = emallocz(sizeof(File)); f->name = estrdup(name); f->parent = parent; f->childlist = parent->child; parent->child = f; parent->ref++; f->ref = 0; filecnt++; } f->ref++; f->qid.type = dir->qid.type; f->qid.vers = dir->qid.vers; f->qidt = uniqueqid(dir); f->qid.path = f->qidt->uniqpath; f->inval = 0; free(dir); return f; } void initroot(void) { Dir *dir; root = emallocz(sizeof(File)); root->name = estrdup("."); dir = dirstat(root->name); if(dir == nil) fatal("root stat"); root->ref = 1; root->qid.vers = dir->qid.vers; root->qidt = uniqueqid(dir); root->qid.path = root->qidt->uniqpath; root->qid.type = QTDIR; free(dir); psmpt = emallocz(sizeof(File)); psmpt->name = estrdup("/"); dir = dirstat(psmpt->name); if(dir == nil) return; psmpt->ref = 1; psmpt->qid.vers = dir->qid.vers; psmpt->qidt = uniqueqid(dir); psmpt->qid.path = psmpt->qidt->uniqpath; free(dir); psmpt = file(psmpt, "mnt"); if(psmpt == 0) return; psmpt = file(psmpt, "exportfs"); } char* makepath(File *p, char *name) { int i, n; char *c, *s, *path, *seg[256]; seg[0] = name; n = strlen(name)+2; for(i = 1; i < 256 && p; i++, p = p->parent){ seg[i] = p->name; n += strlen(p->name)+1; } path = malloc(n); if(path == nil) fatal("out of memory"); s = path; while(i--) { for(c = seg[i]; *c; c++) *s++ = *c; *s++ = '/'; } while(s[-1] == '/') s--; *s = '\0'; return path; } int qidhash(vlong path) { int h, n; h = 0; for(n=0; n<64; n+=Nqidbits){ h ^= path; path >>= Nqidbits; } return h & (Nqidtab-1); } void freeqid(Qidtab *q) { ulong h; Qidtab *l; q->ref--; if(q->ref > 0) return; qfreecnt++; h = qidhash(q->path); if(qidtab[h] == q) qidtab[h] = q->next; else{ for(l=qidtab[h]; l->next!=q; l=l->next) if(l->next == nil) fatal("bad qid list"); l->next = q->next; } free(q); } Qidtab* qidlookup(Dir *d) { ulong h; Qidtab *q; h = qidhash(d->qid.path); for(q=qidtab[h]; q!=nil; q=q->next) if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path) return q; return nil; } int qidexists(vlong path) { int h; Qidtab *q; for(h=0; hnext) if(q->uniqpath == path) return 1; return 0; } Qidtab* uniqueqid(Dir *d) { ulong h; vlong path; Qidtab *q; q = qidlookup(d); if(q != nil){ q->ref++; return q; } path = d->qid.path; while(qidexists(path)){ DEBUG(DFD, "collision on %s\n", d->name); /* collision: find a new one */ ncollision++; path &= QIDPATH; ++newqid; if(newqid >= (1<<16)){ DEBUG(DFD, "collision wraparound\n"); newqid = 1; } path |= newqid<<48; DEBUG(DFD, "assign qid %.16llux\n", path); } q = mallocz(sizeof(Qidtab), 1); if(q == nil) fatal("no memory for qid table"); qidcnt++; q->ref = 1; q->type = d->type; q->dev = d->dev; q->path = d->qid.path; q->uniqpath = path; h = qidhash(d->qid.path); q->next = qidtab[h]; qidtab[h] = q; return q; } void fatal(char *s, ...) { char buf[ERRMAX]; va_list arg; if (s != nil) { va_start(arg, s); vsnprint(buf, ERRMAX, s, arg); va_end(arg); } /* Clear away the slave children */ // for(m = Proclist; m; m = m->next) // postnote(PNPROC, m->pid, "kill"); if (s != nil) { DEBUG(DFD, "%s\n", buf); sysfatal("%s", buf); } else exits(nil); } drawterm-9front-0~git20220608.bee4db6/exportfs/exportfs.h000066400000000000000000000052421424653647700231410ustar00rootroot00000000000000/* * exportfs.h - definitions for exporting file server */ #define DEBUG if(!dbg){}else fprint #define DFD 2 #define fidhash(s) fhash[s%FHASHSIZE] #define Proc Exproc typedef struct Fsrpc Fsrpc; typedef struct Fid Fid; typedef struct File File; typedef struct Proc Proc; typedef struct Qidtab Qidtab; struct Fsrpc { int busy; /* Work buffer has pending rpc to service */ int pid; /* Pid of slave process executing the rpc */ int canint; /* Interrupt gate */ int flushtag; /* Tag on which to reply to flush */ Fcall work; /* Plan 9 incoming Fcall */ uchar *buf; /* Data buffer */ }; struct Fid { int fid; /* system fd for i/o */ File *f; /* File attached to this fid */ int mode; int nr; /* fid number */ int mid; /* Mount id */ Fid *next; /* hash link */ }; struct File { char *name; int ref; Qid qid; Qidtab *qidt; int inval; File *parent; File *child; File *childlist; }; struct Proc { int pid; int busy; Proc *next; }; struct Qidtab { int ref; int type; int dev; vlong path; vlong uniqpath; Qidtab *next; }; enum { MAXPROC = 50, FHASHSIZE = 64, Nr_workbufs = 50, Fidchunk = 1000, Npsmpt = 32, Nqidbits = 5, Nqidtab = (1< #include #include #define Extern extern #include "exportfs.h" char Ebadfid[] = "Bad fid"; char Enotdir[] = "Not a directory"; char Edupfid[] = "Fid already in use"; char Eopen[] = "Fid already opened"; char Exmnt[] = "Cannot .. past mount point"; char Emip[] = "Mount in progress"; char Enopsmt[] = "Out of pseudo mount points"; char Enomem[] = "No memory"; char Eversion[] = "Bad 9P2000 version"; void* emallocz(ulong n) { void *v; v = mallocz(n, 1); if(v == nil) panic("out of memory"); return v; } void Xversion(Fsrpc *t) { Fcall rhdr; if(t->work.msize > messagesize) t->work.msize = messagesize; messagesize = t->work.msize; if(strncmp(t->work.version, "9P2000", 6) != 0){ reply(&t->work, &rhdr, Eversion); return; } rhdr.version = "9P2000"; rhdr.msize = t->work.msize; reply(&t->work, &rhdr, 0); t->busy = 0; } void Xauth(Fsrpc *t) { Fcall rhdr; reply(&t->work, &rhdr, "exportfs: authentication not required"); t->busy = 0; } void Xflush(Fsrpc *t) { Fsrpc *w, *e; Fcall rhdr; e = &Workq[Nr_workbufs]; for(w = Workq; w < e; w++) { if(w->work.tag == t->work.oldtag) { DEBUG(DFD, "\tQ busy %d pid %d can %d\n", w->busy, w->pid, w->canint); if(w->busy && w->pid) { w->flushtag = t->work.tag; DEBUG(DFD, "\tset flushtag %d\n", t->work.tag); // if(w->canint) // postnote(PNPROC, w->pid, "flush"); t->busy = 0; return; } } } reply(&t->work, &rhdr, 0); DEBUG(DFD, "\tflush reply\n"); t->busy = 0; } void Xattach(Fsrpc *t) { Fcall rhdr; Fid *f; f = newfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } if(srvfd >= 0){ /* if(psmpt == 0){ Nomount: reply(&t->work, &rhdr, Enopsmt); t->busy = 0; freefid(t->work.fid); return; } for(i=0; i= Npsmpt) goto Nomount; sprint(buf, "%d", i); f->f = file(psmpt, buf); if(f->f == nil) goto Nomount; sprint(buf, "/mnt/exportfs/%d", i); nfd = dup(srvfd, -1); if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){ errstr(buf, sizeof buf); reply(&t->work, &rhdr, buf); t->busy = 0; freefid(t->work.fid); close(nfd); return; } psmap[i] = 1; f->mid = i; */ }else{ f->f = root; f->f->ref++; } rhdr.qid = f->f->qid; reply(&t->work, &rhdr, 0); t->busy = 0; } Fid* clonefid(Fid *f, int new) { Fid *n; n = newfid(new); if(n == 0) { n = getfid(new); if(n == 0) fatal("inconsistent fids"); if(n->fid >= 0) close(n->fid); freefid(new); n = newfid(new); if(n == 0) fatal("inconsistent fids2"); } n->f = f->f; n->f->ref++; return n; } void Xwalk(Fsrpc *t) { char err[ERRMAX], *e; Fcall rhdr; Fid *f, *nf; File *wf; int i; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } nf = nil; if(t->work.newfid != t->work.fid){ nf = clonefid(f, t->work.newfid); f = nf; } rhdr.nwqid = 0; e = nil; for(i=0; iwork.nwname; i++){ if(i == MAXWELEM){ e = "Too many path elements"; break; } if(strcmp(t->work.wname[i], "..") == 0) { if(f->f->parent == nil) { e = Exmnt; break; } wf = f->f->parent; wf->ref++; goto Accept; } wf = file(f->f, t->work.wname[i]); if(wf == 0){ errstr(err, sizeof err); e = err; break; } Accept: freefile(f->f); rhdr.wqid[rhdr.nwqid++] = wf->qid; f->f = wf; continue; } if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname)) freefid(t->work.newfid); if(rhdr.nwqid > 0) e = nil; reply(&t->work, &rhdr, e); t->busy = 0; } void Xclunk(Fsrpc *t) { Fcall rhdr; Fid *f; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } if(f->fid >= 0) close(f->fid); freefid(t->work.fid); reply(&t->work, &rhdr, 0); t->busy = 0; } void Xstat(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; Dir *d; int s; uchar *statbuf; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } if(f->fid >= 0) d = dirfstat(f->fid); else { path = makepath(f->f, ""); d = dirstat(path); free(path); } if(d == nil) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; return; } d->qid.path = f->f->qidt->uniqpath; s = sizeD2M(d); statbuf = emallocz(s); s = convD2M(d, statbuf, s); free(d); rhdr.nstat = s; rhdr.stat = statbuf; reply(&t->work, &rhdr, 0); free(statbuf); t->busy = 0; } static int getiounit(int fd) { int n; n = iounit(fd); if(n > messagesize-IOHDRSZ) n = messagesize-IOHDRSZ; return n; } void Xcreate(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; File *nf; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } path = makepath(f->f, t->work.name); f->fid = create(path, t->work.mode, t->work.perm); free(path); if(f->fid < 0) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; return; } nf = file(f->f, t->work.name); if(nf == 0) { errstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; return; } f->mode = t->work.mode; freefile(f->f); f->f = nf; rhdr.qid = f->f->qid; rhdr.iounit = getiounit(f->fid); reply(&t->work, &rhdr, 0); t->busy = 0; } void Xremove(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } path = makepath(f->f, ""); DEBUG(DFD, "\tremove: %s\n", path); if(remove(path) < 0) { free(path); errstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; return; } free(path); f->f->inval = 1; if(f->fid >= 0) close(f->fid); freefid(t->work.fid); reply(&t->work, &rhdr, 0); t->busy = 0; } void Xwstat(Fsrpc *t) { char err[ERRMAX], *path; Fcall rhdr; Fid *f; int s; char *strings; Dir d; f = getfid(t->work.fid); if(f == 0) { reply(&t->work, &rhdr, Ebadfid); t->busy = 0; return; } strings = emallocz(t->work.nstat); /* ample */ if(convM2D(t->work.stat, t->work.nstat, &d, strings) <= BIT16SZ){ rerrstr(err, sizeof err); reply(&t->work, &rhdr, err); t->busy = 0; free(strings); return; } if(f->fid >= 0) s = dirfwstat(f->fid, &d); else { path = makepath(f->f, ""); s = dirwstat(path, &d); free(path); } if(s < 0) { rerrstr(err, sizeof err); reply(&t->work, &rhdr, err); } else { /* wstat may really be rename */ if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){ free(f->f->name); f->f->name = estrdup(d.name); } reply(&t->work, &rhdr, 0); } free(strings); t->busy = 0; } void slave(Fsrpc *f) { Proc *p; int pid; static int nproc; for(;;) { for(p = Proclist; p; p = p->next) { if(p->busy == 0) { f->pid = p->pid; p->busy = 1; pid = (uintptr)rendezvous((void*)(uintptr)p->pid, f); if(pid != p->pid) fatal("rendezvous sync fail"); return; } } if(++nproc > MAXPROC) fatal("too many procs"); pid = kproc("slave", blockingslave, nil); DEBUG(DFD, "slave pid %d\n", pid); if(pid == -1) fatal("kproc"); p = malloc(sizeof(Proc)); if(p == 0) fatal("out of memory"); p->busy = 0; p->pid = pid; p->next = Proclist; Proclist = p; DEBUG(DFD, "parent %d rendez\n", pid); rendezvous((void*)(uintptr)pid, p); DEBUG(DFD, "parent %d went\n", pid); } } void blockingslave(void *x) { Fsrpc *p; Fcall rhdr; Proc *m; int pid; USED(x); notify(flushaction); pid = getpid(); DEBUG(DFD, "blockingslave %d rendez\n", pid); m = (Proc*)rendezvous((void*)(uintptr)pid, 0); DEBUG(DFD, "blockingslave %d rendez got %p\n", pid, m); for(;;) { p = rendezvous((void*)(uintptr)pid, (void*)(uintptr)pid); if((uintptr)p == ~(uintptr)0) /* Interrupted */ continue; DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid); if(p->flushtag != NOTAG) goto flushme; switch(p->work.type) { case Tread: slaveread(p); break; case Twrite: slavewrite(p); break; case Topen: slaveopen(p); break; default: reply(&p->work, &rhdr, "exportfs: slave type error"); } if(p->flushtag != NOTAG) { flushme: p->work.type = Tflush; p->work.tag = p->flushtag; reply(&p->work, &rhdr, 0); } p->busy = 0; m->busy = 0; } } int openmount(int sfd) { werrstr("openmount not implemented"); return -1; } void slaveopen(Fsrpc *p) { char err[ERRMAX], *path; Fcall *work, rhdr; Fid *f; Dir *d; work = &p->work; f = getfid(work->fid); if(f == 0) { reply(work, &rhdr, Ebadfid); return; } if(f->fid >= 0) { close(f->fid); f->fid = -1; } path = makepath(f->f, ""); DEBUG(DFD, "\topen: %s %d\n", path, work->mode); p->canint = 1; if(p->flushtag != NOTAG){ free(path); return; } /* There is a race here I ignore because there are no locks */ f->fid = open(path, work->mode); free(path); p->canint = 0; if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) { Error: errstr(err, sizeof err); reply(work, &rhdr, err); return; } f->f->qid = d->qid; free(d); if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */ f->fid = openmount(f->fid); if(f->fid < 0) goto Error; } DEBUG(DFD, "\topen: fd %d\n", f->fid); f->mode = work->mode; rhdr.iounit = getiounit(f->fid); rhdr.qid = f->f->qid; reply(work, &rhdr, 0); } void slaveread(Fsrpc *p) { Fid *f; int n, r; Fcall *work, rhdr; char *data, err[ERRMAX]; work = &p->work; f = getfid(work->fid); if(f == 0) { reply(work, &rhdr, Ebadfid); return; } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; p->canint = 1; if(p->flushtag != NOTAG) return; data = malloc(n); if(data == nil) fatal(Enomem); /* can't just call pread, since directories must update the offset */ r = pread(f->fid, data, n, work->offset); p->canint = 0; if(r < 0) { free(data); errstr(err, sizeof err); reply(work, &rhdr, err); return; } DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r); rhdr.data = data; rhdr.count = r; reply(work, &rhdr, 0); free(data); } void slavewrite(Fsrpc *p) { char err[ERRMAX]; Fcall *work, rhdr; Fid *f; int n; work = &p->work; f = getfid(work->fid); if(f == 0) { reply(work, &rhdr, Ebadfid); return; } n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count; p->canint = 1; if(p->flushtag != NOTAG) return; n = pwrite(f->fid, work->data, n, work->offset); p->canint = 0; if(n < 0) { errstr(err, sizeof err); reply(work, &rhdr, err); return; } DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid); rhdr.count = n; reply(work, &rhdr, 0); } void reopen(Fid *f) { USED(f); fatal("reopen"); } void flushaction(void *a, char *cause) { USED(a); if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) { fprint(2, "exportsrv: note: %s\n", cause); exits("noted"); } if(strncmp(cause, "kill", 4) == 0) noted(NDFLT); noted(NCONT); } drawterm-9front-0~git20220608.bee4db6/glenda-t.ico000066400000000000000000000221561424653647700214360ustar00rootroot00000000000000h6 @@(F(   """###%%%&&&'''((()))***+++---...000222333444555777EEEFFFHHHOOOPPPWWW___}}} !  )6(/  ''!.*M   %-MMMLH ' MM, MMGFDMMM L>8GA BMMMMMMMMK972+AMMMMMMFMB0$<:MMMMMM"!))#MMMMMMM MMMM4/3MMMMMMM )MMMMMMMMG&CMMMMMMMM=1IMJ%@MMMMMMMMMIE?M?7MMMMMMMMMMMMM5;FMMMMMMMMMMMMMM8MMMMMMMM( @  !!!"""###$$$%%%&&&'''((()))***---...///000111222333555666777888999:::;;;<<<===>>>???@@@AAADDDEEEFFFGGGIIILLLMMMOOORRRSSSUUUVVVWWW[[[\\\___aaabbbccchhhiiimmmqqqsssuuuxxx|||#))  (1% !,<# & **4>;3 Z?  +.7:<33 ,    %& %/ &<)d  1#2I' S .9 )$%5    & 1:   %   $ (  F  # vqu b }\Vjc Og[TQI=Bj! UYAHaK! %-4C(   1 MW' L"*  o6@9&O 0 -4$D  n|"4:  00@E  !"!($*4zx  "$8!v].zl)*b{-R:iM2&kNE_yG6r8^7mX`!%\JPfwhKept~s7(@  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmpppqqqrrrssstttuuuvvvxxxyyyzzz|||}}}~~~ (',&+$' $"  "  &+3< < 1,:F'(%  $    #6.''3^! ,-EM$5*  $&!   5&&,ct_31'  '0AfU8   #!  '   +0./=FN>568:' $%/6B!    $! !55595MHF67==9:  +(:     # 1>5/$@<;B?C=5,#  $      " &#((,(&!,5ID ' 0      $,$ 9E !<        * #64 '!+     $%%%103'#A=6#-.'        !"!.1E )31:         (3,./ (3.1:@        4@  %21E<       W  .!'90J  M    &*:BY      -,5' | /!&(.       .+     $*6     #   %  >J    -гwΕ c  ˲xr<  ڴ3(Pla)  p7b|}c.0DmgYMA~ Zsvj`3659H2>s   `lp~{-Sǧg;W! ~Exd2ÜbKD'{J 'ϿҾNG78Y둜C4' jMI*H7q!-V  zRWPTKW92<5U9*$   X 'YXX7 !x21 *^  "D@[\+%IS$O\\TS>@F#GZS5'K#d|~KQu[/-?i Dhyyoif[fN?4("  b V=IHH< (l%$4ITJ  K1-)*77I  L,01.>EIS   \ -2.2-6@R   H8'0*,)/+.:8H   !# !!*-$-/45뎝 ""*$(;F  !-߰j! '%%)nWB+!#!&)#(lW+*`!!!#"#$""%\ِ4/Lk&('-2'((V/X.%i话<_:*=uU?,Q={s&%CxL0Je8:+e/\2A閍hژ2U(>A7xVJjj;mpeL+%c돠L<]fՇٛeCޗ{a[mP_$Ӓc$eJ霒Zk drawterm-9front-0~git20220608.bee4db6/gui-android/Makefile000066400000000000000000000016161424653647700231070ustar00rootroot00000000000000ROOT=.. include ../Make.config LIB=libgui.a OFILES=\ cpp/android.$O\ cpp/native-lib.$O\ cpp/devandroid.$O\ default: $(LIB) gen/org/echoline/drawterm/R.java bin/classes.dex $(LIB): $(OFILES) $(AR) r $(LIB) $(OFILES) $(RANLIB) $(LIB) gen/org/echoline/drawterm/R.java: $(shell find res/ -type f) $(SDKPREFIX)/build-tools/30.0.3/aapt package -f -m -M AndroidManifest.xml -I $(SDKPREFIX)/platforms/android-21/android.jar -S res/ -J gen bin/classes.dex: obj/org/echoline/drawterm/MainActivity.class obj/org/echoline/drawterm/DrawTermThread.class obj/org/echoline/drawterm/MySurfaceView.class $(SDKPREFIX)/build-tools/30.0.3/dx --dex --verbose --output=$@ obj/ obj/org/echoline/drawterm/%.class: java/org/echoline/drawterm/%.java $(JAVA_HOME)/bin/javac -d obj/ -classpath $(SDKPREFIX)/platforms/android-21/android.jar -sourcepath java java/org/echoline/drawterm/$*.java gen/org/echoline/drawterm/R.java drawterm-9front-0~git20220608.bee4db6/gui-android/cpp/000077500000000000000000000000001424653647700222255ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/gui-android/cpp/android.c000066400000000000000000000120131424653647700240060ustar00rootroot00000000000000#include #include #include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include #include #include #include #include "screen.h" Memimage *gscreen = nil; extern int screenWidth; extern int screenHeight; extern ANativeWindow *window; extern jobject mainActivityObj; extern JavaVM *jvm; char* clipread(void) { char *ret; const char *s; JNIEnv *env; jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL); if (rs != JNI_OK) { __android_log_print(ANDROID_LOG_WARN, "drawterm", "AttachCurrentThread returned error: %d", rs); return strdup(""); } jclass clazz = (*env)->GetObjectClass(env, mainActivityObj); jmethodID methodID = (*env)->GetMethodID(env, clazz, "getClipBoard", "()Ljava/lang/String;"); jstring str = (jstring)(*env)->CallObjectMethod(env, mainActivityObj, methodID); s = (*env)->GetStringUTFChars(env, str, NULL); ret = strdup(s); (*env)->ReleaseStringUTFChars(env, str, s); (*jvm)->DetachCurrentThread(jvm); return ret; } int clipwrite(char *buf) { JNIEnv *env; jint rs = (*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6); if(rs != JNI_OK) { __android_log_print(ANDROID_LOG_WARN, "drawterm", "GetEnv returned error: %d", rs); return 0; } jclass clazz = (*env)->GetObjectClass(env, mainActivityObj); jmethodID methodID = (*env)->GetMethodID(env, clazz, "setClipBoard", "(Ljava/lang/String;)V"); jstring str = (*env)->NewStringUTF(env, buf); (*env)->CallVoidMethod(env, mainActivityObj, methodID, str); return 0; } void show_notification(char *buf) { JNIEnv *env; jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL); if(rs != JNI_OK) { __android_log_print(ANDROID_LOG_WARN, "drawterm", "AttachCurrentThread returned error: %d", rs); return; } jclass clazz = (*env)->GetObjectClass(env, mainActivityObj); jmethodID methodID = (*env)->GetMethodID(env, clazz, "showNotification", "(Ljava/lang/String;)V"); jstring str = (*env)->NewStringUTF(env, buf); (*env)->CallVoidMethod(env, mainActivityObj, methodID, str); (*jvm)->DetachCurrentThread(jvm); return; } int num_cameras() { JNIEnv *env; int n; jint rs = (*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6); if(rs != JNI_OK) { __android_log_print(ANDROID_LOG_WARN, "drawterm", "GetEnv returned error: %d", rs); return 0; } jclass clazz = (*env)->GetObjectClass(env, mainActivityObj); jmethodID methodID = (*env)->GetMethodID(env, clazz, "numCameras", "()I"); n = (*env)->CallIntMethod(env, mainActivityObj, methodID); return n; } void take_picture(int id) { JNIEnv *env; jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL); if(rs != JNI_OK) { __android_log_print(ANDROID_LOG_WARN, "drawterm", "AttachCurrentThread returned error: %d", rs); return; } jclass clazz = (*env)->GetObjectClass(env, mainActivityObj); jmethodID methodID = (*env)->GetMethodID(env, clazz, "takePicture", "(I)V"); (*env)->CallVoidMethod(env, mainActivityObj, methodID, id); (*jvm)->DetachCurrentThread(jvm); return; } void setcolor(ulong i, ulong r, ulong g, ulong b) { return; } void getcolor(ulong v, ulong *r, ulong *g, ulong *b) { *r = (v>>16)&0xFF; *g = (v>>8)&0xFF; *b = v&0xFF; } void flushmemscreen(Rectangle r) { ANativeWindow_Buffer buffer; uint8_t *pixels; int x, y, o, b; ARect bounds; if (window == NULL) return; memset(&buffer, 0, sizeof(buffer)); bounds.left = r.min.x; bounds.top = r.min.y; bounds.right = r.max.x; bounds.bottom = r.max.y; if (ANativeWindow_lock(window, &buffer, &bounds) != 0) { __android_log_print(ANDROID_LOG_WARN, "drawterm", "Unable to lock window buffer"); return; } r.min.x = bounds.left; r.min.y = bounds.top; r.max.x = bounds.right; r.max.y = bounds.bottom; pixels = (uint8_t*)buffer.bits; for (y = r.min.y; y < r.max.y; y++) for (x = r.min.x; x < r.max.x; x++) { o = (y * screenWidth + x) * 4; b = (y * buffer.stride + x) * 4; pixels[b+3] = 0xFF; pixels[b+2] = gscreen->data->bdata[o+0]; pixels[b+1] = gscreen->data->bdata[o+1]; pixels[b+0] = gscreen->data->bdata[o+2]; } if (ANativeWindow_unlockAndPost(window) != 0) { __android_log_print(ANDROID_LOG_WARN, "drawterm", "Unable to unlock and post window buffer"); } return; } void screeninit(void) { Rectangle r = Rect(0,0,screenWidth,screenHeight); memimageinit(); screensize(r, XRGB32); if (gscreen == nil) panic("screensize failed"); gscreen->clipr = r; terminit(); qlock(&drawlock); flushmemscreen(r); qunlock(&drawlock); return; } void screensize(Rectangle r, ulong chan) { Memimage *mi; mi = allocmemimage(r, chan); if (mi == nil) return; if (gscreen != nil) freememimage(gscreen); gscreen = mi; gscreen->clipr = ZR; } Memdata* attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen) { *r = gscreen->clipr; *depth = gscreen->depth; *chan = gscreen->chan; *width = gscreen->width; *softscreen = 1; gscreen->data->ref++; return gscreen->data; } void setcursor(void) { return; } void mouseset(Point xy) { return; } void guimain(void) { cpubody(); } drawterm-9front-0~git20220608.bee4db6/gui-android/cpp/devandroid.c000066400000000000000000000117151424653647700245150ustar00rootroot00000000000000#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include #include void show_notification(char *buf); void take_picture(int id); int num_cameras(); int Ncameras = 0; uchar *cambuf = nil; int camlen; ASensorManager *sensorManager = NULL; enum { Qdir = 0, Qcam = 1, Qaccel = 2, Qcompass = 4, Qnotification = 6, }; #define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y)) static void androidinit(void); static void androidinit(void) { sensorManager = ASensorManager_getInstance(); Ncameras = num_cameras(); } static Chan* androidattach(char *param) { Chan *c; c = devattach('N', param); c->qid.path = QID(0, 0, Qdir); c->qid.type = QTDIR; c->qid.vers = 0; return c; } static int androidgen(Chan *c, char *n, Dirtab *d, int nd, int s, Dir *dp) { Qid q; if (s == DEVDOTDOT) { mkqid(&q, Qdir, 0, QTDIR); devdir(c, q, "#N", 0, eve, 0555, dp); return 1; } if (s < Ncameras) { sprintf(up->genbuf, "cam%d.jpg", s); mkqid(&q, (s << 16) | Qcam, 0, QTFILE); devdir(c, q, up->genbuf, 0, eve, 0444, dp); return 1; } if (s == Ncameras) { sprintf(up->genbuf, "accel"); mkqid(&q, Qaccel, 0, QTFILE); devdir(c, q, up->genbuf, 0, eve, 0444, dp); return 1; } if (s == (Ncameras+1)) { sprintf(up->genbuf, "compass"); mkqid(&q, Qcompass, 0, QTFILE); devdir(c, q, up->genbuf, 0, eve, 0444, dp); return 1; } if (s == (Ncameras+2)) { sprintf(up->genbuf, "notification"); mkqid(&q, Qnotification, 0, QTFILE); devdir(c, q, up->genbuf, 0, eve, 0222, dp); return 1; } return -1; } static Walkqid* androidwalk(Chan *c, Chan *nc, char **name, int nname) { return devwalk(c, nc, name, nname, 0, 0, androidgen); } static int androidstat(Chan *c, uchar *db, int n) { return devstat(c, db, n, 0, 0, androidgen); } static Chan* androidopen(Chan *c, int omode) { p9_uvlong s; c = devopen(c, omode, 0, 0, androidgen); if (c->qid.path & Qcam) { s = c->qid.path >> 16; take_picture(s); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; c->iounit = 8192; return c; } static void androidclose(Chan *c) { if (c->qid.path & Qcam && cambuf != nil) { free(cambuf); cambuf = nil; } } static long androidread(Chan *c, void *v, long n, vlong off) { char *a = v; long l; const ASensor *sensor; ASensorEventQueue *queue = NULL; ASensorEvent data; switch((ulong)c->qid.path & 0xF) { default: error(Eperm); return -1; case Qcam: while(cambuf == nil) usleep(10 * 1000); l = camlen - off; if (l > n) l = n; if (l > 0) memcpy(a, cambuf + off, l); return l; case Qaccel: queue = ASensorManager_createEventQueue(sensorManager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), 1, NULL, NULL); if (queue == NULL) return 0; sensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER); if (sensor == NULL) { ASensorManager_destroyEventQueue(sensorManager, queue); return 0; } if (ASensorEventQueue_enableSensor(queue, sensor)) { ASensorEventQueue_disableSensor(queue, sensor); ASensorManager_destroyEventQueue(sensorManager, queue); return 0; } l = 0; if (ALooper_pollAll(1000, NULL, NULL, NULL) == 1) { if (ASensorEventQueue_getEvents(queue, &data, 1)) { l = snprint(a, n, "%11f %11f %11f\n", data.vector.x, data.vector.y, data.vector.z); } } ASensorEventQueue_disableSensor(queue, sensor); ASensorManager_destroyEventQueue(sensorManager, queue); return l; case Qcompass: queue = ASensorManager_createEventQueue(sensorManager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), 1, NULL, NULL); if (queue == NULL) return 0; sensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_MAGNETIC_FIELD); if (sensor == NULL) { ASensorManager_destroyEventQueue(sensorManager, queue); return 0; } if (ASensorEventQueue_enableSensor(queue, sensor)) { ASensorEventQueue_disableSensor(queue, sensor); ASensorManager_destroyEventQueue(sensorManager, queue); return 0; } l = 0; if (ALooper_pollAll(1000, NULL, NULL, NULL) == 1) { if (ASensorEventQueue_getEvents(queue, &data, 1)) { l = snprint(a, n, "%11f %11f %11f\n", data.vector.x, data.vector.y, data.vector.z); } } ASensorEventQueue_disableSensor(queue, sensor); ASensorManager_destroyEventQueue(sensorManager, queue); return l; case Qdir: return devdirread(c, a, n, 0, 0, androidgen); } } static long androidwrite(Chan *c, void *vp, long n, vlong off) { char *a = vp; char *str; switch((ulong)c->qid.path) { case Qnotification: str = malloc(n+1); memcpy(str, a, n); str[n] = '\0'; show_notification(str); free(str); return n; default: error(Eperm); break; } return -1; } Dev androiddevtab = { 'N', "android", devreset, androidinit, devshutdown, androidattach, androidwalk, androidstat, androidopen, devcreate, androidclose, androidread, devbread, androidwrite, devbwrite, devremove, devwstat, }; drawterm-9front-0~git20220608.bee4db6/gui-android/cpp/native-lib.c000066400000000000000000000101551424653647700244250ustar00rootroot00000000000000#include #include #include #include #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include #include #include void absmousetrack(int, int, int, ulong); ulong ticks(void); int dt_main(int, char**); int screenWidth; int screenHeight; Point mousept = {0, 0}; int buttons = 0; float ws = 1; float hs = 1; extern char *snarfbuf; int mPaused = 0; ANativeWindow *window = NULL; jobject mainActivityObj; JavaVM *jvm; void flushmemscreen(Rectangle r); extern uchar *cambuf; extern int camlen; JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_setObject( JNIEnv *env, jobject obj) { mainActivityObj = (*env)->NewGlobalRef(env, obj); jint rs = (*env)->GetJavaVM(env, &jvm); assert(rs == JNI_OK); } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_keyDown( JNIEnv *env, jobject obj, jint c) { kbdkey(c, 1); } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_keyUp( JNIEnv *env, jobject obj, jint c) { kbdkey(c, 0); } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_setPass( JNIEnv *env, jobject obj, jstring str) { setenv("PASS", (char*)(*env)->GetStringUTFChars(env, str, 0), 1); } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_setWidth( JNIEnv *env, jobject obj, jint width) { screenWidth = width; } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_setHeight( JNIEnv *env, jobject obj, jint height) { screenHeight = height; } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_setWidthScale( JNIEnv *env, jobject obj, jfloat s) { ws = s; } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_setHeightScale( JNIEnv *env, jobject obj, jfloat s) { hs = s; } JNIEXPORT jint JNICALL Java_org_echoline_drawterm_MainActivity_dtmain( JNIEnv *env, jobject obj, jobjectArray argv) { int i, ret; char **args = (char **) malloc(((*env)->GetArrayLength(env, argv)+1) * sizeof(char *)); for (i = 0; i < (*env)->GetArrayLength(env, argv); i++) { jobject str = (jobject) (*env)->GetObjectArrayElement(env, argv, i); args[i] = strdup((char*)(*env)->GetStringUTFChars(env, (jstring)str, 0)); } args[(*env)->GetArrayLength(env, argv)] = NULL; ret = dt_main(i, args); for (i = 0; args[i] != NULL; i++) { free(args[i]); } free(args); return ret; } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_setMouse( JNIEnv *env, jobject obj, jintArray args) { jboolean isCopy; jint *data; if ((*env)->GetArrayLength(env, args) < 3) return; data = (*env)->GetIntArrayElements(env, args, &isCopy); mousept.x = (int)(data[0] / ws); mousept.y = (int)(data[1] / hs); buttons = data[2]; (*env)->ReleaseIntArrayElements(env, args, data, 0); absmousetrack(mousept.x, mousept.y, buttons, ticks()); } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_setDTSurface( JNIEnv* jenv, jobject obj, jobject surface) { if (surface != NULL) { window = ANativeWindow_fromSurface(jenv, surface); ANativeWindow_setBuffersGeometry(window, screenWidth, screenHeight, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM); flushmemscreen(Rect(0, 0, screenWidth, screenHeight)); } else if (window != NULL) { ANativeWindow_release(window); window = NULL; } } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_exitDT( JNIEnv* jenv, jobject obj) { exit(0); } JNIEXPORT void JNICALL Java_org_echoline_drawterm_MainActivity_sendPicture( JNIEnv* env, jobject obj, jbyteArray array) { jint len = (*env)->GetArrayLength(env, array); jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL); camlen = len; cambuf = malloc(camlen); memcpy(cambuf, bytes, camlen); (*env)->ReleaseByteArrayElements(env, array, bytes, 0); } drawterm-9front-0~git20220608.bee4db6/gui-android/java/000077500000000000000000000000001424653647700223645ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/gui-android/java/org/000077500000000000000000000000001424653647700231535ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/gui-android/java/org/echoline/000077500000000000000000000000001424653647700247415ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/gui-android/java/org/echoline/drawterm/000077500000000000000000000000001424653647700265665ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/gui-android/java/org/echoline/drawterm/DrawTermThread.java000066400000000000000000000011011424653647700322770ustar00rootroot00000000000000package org.echoline.drawterm; /** * Created by eli on 12/4/17. */ public class DrawTermThread extends Thread { private MainActivity m; private String p; private String []args; public DrawTermThread(String []args, String p, MainActivity m) { this.m = m; this.p = p; this.args = args; } @Override public void run() { if (p != null && !p.equals("")) m.setPass(p); m.dtmain(args); m.runOnUiThread(new Runnable() { @Override public void run() { m.exitDT(); m.setContentView(R.layout.server_main); m.populateServers(m); } }); } } drawterm-9front-0~git20220608.bee4db6/gui-android/java/org/echoline/drawterm/MainActivity.java000066400000000000000000000315721424653647700320420ustar00rootroot00000000000000package org.echoline.drawterm; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.Point; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.Display; import android.view.MotionEvent; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.view.Surface; import android.view.inputmethod.InputMethodManager; import android.view.KeyEvent; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.content.ClipData; import android.content.ClipboardManager; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CameraCaptureSession; import android.hardware.camera2.TotalCaptureResult; import android.media.Image; import android.media.ImageReader; import android.graphics.ImageFormat; import android.os.Handler; import android.os.HandlerThread; import java.io.File; import java.util.Map; import java.nio.ByteBuffer; import java.util.List; import java.util.ArrayList; public class MainActivity extends Activity { private Map map; private MainActivity mainActivity; private boolean dtrunning = false; private DrawTermThread dthread; private int notificationId; private CameraDevice cameraDevice = null; private byte []jpegBytes; static { System.loadLibrary("drawterm"); } public void showNotification(String text) { Notification.Builder builder = new Notification.Builder(this) .setDefaults(Notification.DEFAULT_SOUND) .setSmallIcon(R.drawable.ic_small) .setContentText(text) .setStyle(new Notification.BigTextStyle().bigText(text)) .setPriority(Notification.PRIORITY_DEFAULT); ((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE)).notify(notificationId, builder.build()); notificationId++; } public int numCameras() { try { return ((CameraManager)getSystemService(Context.CAMERA_SERVICE)).getCameraIdList().length; } catch (CameraAccessException e) { Log.w("drawterm", e.toString()); return 0; } } public void takePicture(int id) { try { HandlerThread mBackgroundThread = new HandlerThread("Camera Background"); mBackgroundThread.start(); Handler mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE); String []cameraIdList = manager.getCameraIdList(); manager.openCamera(cameraIdList[id], new CameraDevice.StateCallback() { public void onOpened(CameraDevice device) { cameraDevice = device; } public void onDisconnected(CameraDevice device) { if (cameraDevice != null) cameraDevice.close(); cameraDevice = null; } public void onError(CameraDevice device, int error) { if (cameraDevice != null) cameraDevice.close(); cameraDevice = null; } }, mBackgroundHandler); ImageReader reader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1); CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG); captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); captureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO); captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON); captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getWindowManager().getDefaultDisplay().getRotation()); captureBuilder.addTarget(reader.getSurface()); reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { public void onImageAvailable(ImageReader reader) { Image image = null; try { image = reader.acquireLatestImage(); ByteBuffer buffer = image.getPlanes()[0].getBuffer(); jpegBytes = new byte[buffer.capacity()]; buffer.get(jpegBytes); } catch (Exception e) { Log.w("drawterm", e.toString()); } finally { if (image != null) { image.close(); } } } }, mBackgroundHandler); List outputSurfaces = new ArrayList(1); outputSurfaces.add(reader.getSurface()); cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { public void onConfigured(CameraCaptureSession session) { try { List captureRequests = new ArrayList(10); for (int i = 0; i < 10; i++) captureRequests.add(captureBuilder.build()); session.captureBurst(captureRequests, new CameraCaptureSession.CaptureCallback() { public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) { try { sendPicture(jpegBytes); mBackgroundThread.quitSafely(); mBackgroundThread.join(); } catch (Exception e) { Log.w("drawterm", e.toString()); } } }, mBackgroundHandler); } catch (CameraAccessException e) { e.printStackTrace(); } } public void onConfigureFailed(CameraCaptureSession session) { } }, mBackgroundHandler); } catch (Exception e) { e.printStackTrace(); } } public void serverView(View v) { setContentView(R.layout.server_main); serverButtons(); String s = (String)map.get(((TextView)v).getText().toString()); String []a = s.split("\007"); ((EditText)findViewById(R.id.cpuServer)).setText((String)a[0]); ((EditText)findViewById(R.id.authServer)).setText((String)a[1]); ((EditText)findViewById(R.id.userName)).setText((String)a[2]); if (a.length > 3) ((EditText)findViewById(R.id.passWord)).setText((String)a[3]); } public void populateServers(Context context) { ListView ll = (ListView)findViewById(R.id.servers); ArrayAdapter la = new ArrayAdapter(this, R.layout.item_main); SharedPreferences settings = getSharedPreferences("DrawtermPrefs", 0); map = (Map)settings.getAll(); String key; Object []keys = map.keySet().toArray(); for (int i = 0; i < keys.length; i++) { key = (String)keys[i]; la.add(key); } ll.setAdapter(la); setDTSurface(null); dtrunning = false; } public void runDrawterm(String []args, String pass) { Resources res = getResources(); DisplayMetrics dm = res.getDisplayMetrics(); int wp = dm.widthPixels; int hp = dm.heightPixels; setContentView(R.layout.drawterm_main); Button kbutton = (Button)findViewById(R.id.keyboardToggle); kbutton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, 0); } }); int rid = res.getIdentifier("navigation_bar_height", "dimen", "android"); if (rid > 0) { hp -= res.getDimensionPixelSize(rid); } LinearLayout ll = (LinearLayout)findViewById(R.id.dtButtons); hp -= ll.getHeight(); int w = (int)(wp * (160.0/dm.xdpi)); int h = (int)(hp * (160.0/dm.ydpi)); float ws = (float)wp/w; float hs = (float)hp/h; // only scale up if (ws < 1) { ws = 1; w = wp; } if (hs < 1) { hs = 1; h = hp; } MySurfaceView mView = new MySurfaceView(mainActivity, w, h, ws, hs); mView.getHolder().setFixedSize(w, h); LinearLayout l = (LinearLayout)findViewById(R.id.dlayout); l.addView(mView, 1, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); dthread = new DrawTermThread(args, pass, mainActivity); dthread.start(); dtrunning = true; } public void serverButtons() { Button button = (Button)findViewById(R.id.save); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String cpu = ((EditText)findViewById(R.id.cpuServer)).getText().toString(); String auth = ((EditText)findViewById(R.id.authServer)).getText().toString(); String user = ((EditText)findViewById(R.id.userName)).getText().toString(); String pass = ((EditText)findViewById(R.id.passWord)).getText().toString(); SharedPreferences settings = getSharedPreferences("DrawtermPrefs", 0); SharedPreferences.Editor editor = settings.edit(); editor.putString(user + "@" + cpu + " (auth=" + auth + ")", cpu + "\007" + auth + "\007" + user + "\007" + pass); editor.commit(); } }); button = (Button) findViewById(R.id.connect); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View view) { String cpu = ((EditText)findViewById(R.id.cpuServer)).getText().toString(); String auth = ((EditText)findViewById(R.id.authServer)).getText().toString(); String user = ((EditText)findViewById(R.id.userName)).getText().toString(); String pass = ((EditText)findViewById(R.id.passWord)).getText().toString(); String args[] = {"drawterm", "-p", "-h", cpu, "-a", auth, "-u", user}; runDrawterm(args, pass); } }); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mainActivity = this; setObject(); setContentView(R.layout.activity_main); populateServers(this); View fab = findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setContentView(R.layout.server_main); serverButtons(); } }); } @Override public boolean dispatchKeyEvent(KeyEvent event) { if (!dtrunning) { return super.dispatchKeyEvent(event); } int k = event.getUnicodeChar(); if (k == 0) { k = event.getDisplayLabel(); if (k >= 'A' && k <= 'Z') k |= 0x20; } String chars = event.getCharacters(); if (k == 0 && chars != null) { for (int i = 0; i < chars.length(); i++) { k = chars.codePointAt(i); keyDown(k); keyUp(k); } return true; } if (k == 0) switch (event.getKeyCode()) { case KeyEvent.KEYCODE_DEL: k = 0x0008; break; case KeyEvent.KEYCODE_FORWARD_DEL: k = 0x007F; break; case KeyEvent.KEYCODE_ESCAPE: k = 0x001B; break; case KeyEvent.KEYCODE_MOVE_HOME: k = 0xF00D; break; case KeyEvent.KEYCODE_MOVE_END: k = 0xF018; break; case KeyEvent.KEYCODE_PAGE_UP: k = 0xF00F; break; case KeyEvent.KEYCODE_PAGE_DOWN: k = 0xF013; break; case KeyEvent.KEYCODE_INSERT: k = 0xF014; break; case KeyEvent.KEYCODE_SYSRQ: k = 0xF010; break; case KeyEvent.KEYCODE_DPAD_UP: k = 0xF00E; break; case KeyEvent.KEYCODE_DPAD_LEFT: k = 0xF011; break; case KeyEvent.KEYCODE_DPAD_RIGHT: k = 0xF012; break; case KeyEvent.KEYCODE_DPAD_DOWN: k = 0xF800; break; } if (k == 0) return true; if (event.isCtrlPressed()) { keyDown(0xF017); } if (event.isAltPressed() && k < 128) { keyDown(0xF015); } if (event.getAction() == KeyEvent.ACTION_DOWN) { keyDown(k); } else if (event.getAction() == KeyEvent.ACTION_UP) { keyUp(k); } if (event.isCtrlPressed()) { keyUp(0xF017); } if (event.isAltPressed() && k < 128) { keyUp(0xF015); } return true; } @Override public void onBackPressed() { } @Override public void onDestroy() { setDTSurface(null); dtrunning = false; exitDT(); super.onDestroy(); } public void setClipBoard(String str) { ClipboardManager cm = (ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE); if (cm != null) { ClipData cd = ClipData.newPlainText(null, str); cm.setPrimaryClip(cd); } } public String getClipBoard() { ClipboardManager cm = (ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE); if (cm != null) { ClipData cd = cm.getPrimaryClip(); if (cd != null) return (String)(cd.getItemAt(0).coerceToText(mainActivity.getApplicationContext()).toString()); } return ""; } public native void dtmain(Object[] args); public native void setPass(String arg); public native void setWidth(int arg); public native void setHeight(int arg); public native void setWidthScale(float arg); public native void setHeightScale(float arg); public native void setDTSurface(Surface surface); public native void setMouse(int[] args); public native void setObject(); public native void keyDown(int c); public native void keyUp(int c); public native void exitDT(); public native void sendPicture(byte[] array); } drawterm-9front-0~git20220608.bee4db6/gui-android/java/org/echoline/drawterm/MySurfaceView.java000066400000000000000000000052571424653647700321730ustar00rootroot00000000000000package org.echoline.drawterm; import android.util.Log; import android.content.Context; import android.graphics.Bitmap; import android.os.SystemClock; import android.view.MotionEvent; import android.view.SurfaceView; import android.view.SurfaceHolder; import android.view.View; import android.widget.CheckBox; import android.widget.EditText; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.security.spec.ECField; /** * Created by eli on 12/3/17. */ public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { private int screenWidth, screenHeight; private MainActivity mainActivity; private float ws, hs; public MySurfaceView(Context context, int w, int h, float ws, float hs) { super(context); screenHeight = h; screenWidth = w; this.ws = ws; this.hs = hs; mainActivity = (MainActivity)context; mainActivity.setWidth(screenWidth); mainActivity.setHeight(screenHeight); mainActivity.setWidthScale(ws); mainActivity.setHeightScale(hs); setWillNotDraw(true); getHolder().addCallback(this); setOnTouchListener(new View.OnTouchListener() { private int[] mouse = new int[3]; @Override public boolean onTouch(View v, MotionEvent event) { CheckBox left = (CheckBox)mainActivity.findViewById(R.id.mouseLeft); CheckBox middle = (CheckBox)mainActivity.findViewById(R.id.mouseMiddle); CheckBox right = (CheckBox)mainActivity.findViewById(R.id.mouseRight); CheckBox up = (CheckBox)mainActivity.findViewById(R.id.mouseUp); CheckBox down = (CheckBox)mainActivity.findViewById(R.id.mouseDown); int buttons = (left.isChecked()? 1: 0) | (middle.isChecked()? 2: 0) | (right.isChecked()? 4: 0) | (up.isChecked()? 8: 0) | (down.isChecked()? 16: 0); if (event.getAction() == MotionEvent.ACTION_DOWN) { mouse[0] = Math.round(event.getX()); mouse[1] = Math.round(event.getY()); mouse[2] = buttons; mainActivity.setMouse(mouse); } else if (event.getAction() == MotionEvent.ACTION_MOVE) { mouse[0] = Math.round(event.getX()); mouse[1] = Math.round(event.getY()); mouse[2] = buttons; mainActivity.setMouse(mouse); } else if (event.getAction() == MotionEvent.ACTION_UP) { mouse[0] = Math.round(event.getX()); mouse[1] = Math.round(event.getY()); mouse[2] = 0; mainActivity.setMouse(mouse); } return true; } }); } @Override public void surfaceCreated(SurfaceHolder holder) { mainActivity.setDTSurface(holder.getSurface()); } @Override public void surfaceChanged(SurfaceHolder holder, int w, int h, int format) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { mainActivity.setDTSurface(null); } } drawterm-9front-0~git20220608.bee4db6/gui-android/res/000077500000000000000000000000001424653647700222345ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/gui-android/res/layout/000077500000000000000000000000001424653647700235515ustar00rootroot00000000000000drawterm-9front-0~git20220608.bee4db6/gui-android/res/layout/activity_main.xml000066400000000000000000000013261424653647700271350ustar00rootroot00000000000000