shithub: drawterm-fdroid

Download patch

ref: 66ff6da6086588952ff870dd41a86058fde1d8e9
parent: 1361c96b22e5d09a99d4fbfac1df1cb8cf23551d
parent: b2527a724b7a3fc8bd1c4bc9ba6a7bc6032bc47d
author: Eli Cohen <echoline@gmail.com>
date: Thu Mar 31 12:41:10 EDT 2022

merge

--- /dev/null
+++ b/Make.alsa
@@ -1,0 +1,23 @@
+# Unix
+#PTHREAD=	# for Mac
+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 -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)
--- a/Make.android
+++ b/Make.android
@@ -1,6 +1,5 @@
 # Android
-SDKPREFIX=$(HOME)/Android/Sdk
-JAVA_HOME=/usr
+include Make.android.config
 OBJS=lib/arm64-v8a/libdrawterm.so lib/armeabi-v7a/libdrawterm.so lib/x86/libdrawterm.so lib/x86_64/libdrawterm.so
 
 all: drawterm.apk
@@ -25,14 +24,14 @@
 	CONF=android-amd64 make clean;
 
 drawterm.apk: drawterm-signed.apk
-	$(SDKPREFIX)/build-tools/30.0.3/zipalign -v -f 4 $< $@
+	$(SDKPREFIX)/build-tools/$(BUILDTOOLS)/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
+	$(JAVA_HOME)/bin/jarsigner -verbose -keystore ./drawterm.keystore -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)
+	$(SDKPREFIX)/build-tools/$(BUILDTOOLS)/aapt package -v -f -M gui-android/AndroidManifest.xml -S gui-android/res -I $(SDKPREFIX)/platforms/android-$(PLATFORM)/android.jar -F $@ gui-android/bin
+	$(SDKPREFIX)/build-tools/$(BUILDTOOLS)/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
+	$(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=9front,O=Android,C=US" -keystore $@ -alias drawtermKey -keyalg RSA -v
--- a/Make.android-386
+++ b/Make.android-386
@@ -1,7 +1,5 @@
 # Android
-SDKPREFIX=$(HOME)/Android/Sdk
-NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
-JAVA_HOME=/usr
+include $(ROOT)/Make.android.config
 
 PTHREAD=-pthread
 AR=$(NDKPREFIX)/i686-linux-android-ar
@@ -8,7 +6,7 @@
 AS=$(NDKPREFIX)/i686-linux-android-as
 RANLIB=$(NDKPREFIX)/i686-linux-android-ranlib
 STRIP=$(NDKPREFIX)/i686-linux-android-strip
-CC=$(NDKPREFIX)/i686-linux-android21-clang
+CC=$(NDKPREFIX)/i686-linux-android$(PLATFORM)-clang
 CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC
 O=o
 OS=posix
--- a/Make.android-amd64
+++ b/Make.android-amd64
@@ -1,7 +1,5 @@
 # Android
-SDKPREFIX=$(HOME)/Android/Sdk
-NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
-JAVA_HOME=/usr
+include $(ROOT)/Make.android.config
 
 PTHREAD=-pthread
 AR=$(NDKPREFIX)/x86_64-linux-android-ar
@@ -8,7 +6,7 @@
 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
+CC=$(NDKPREFIX)/x86_64-linux-android$(PLATFORM)-clang
 CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC
 O=o
 OS=posix
--- a/Make.android-arm
+++ b/Make.android-arm
@@ -1,7 +1,5 @@
 # Android
-SDKPREFIX=$(HOME)/Android/Sdk
-NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
-JAVA_HOME=/usr
+include $(ROOT)/Make.android.config
 
 PTHREAD=-pthread
 AR=$(NDKPREFIX)/arm-linux-androideabi-ar
@@ -8,7 +6,7 @@
 AS=$(NDKPREFIX)/arm-linux-androideabi-as
 RANLIB=$(NDKPREFIX)/arm-linux-androideabi-ranlib
 STRIP=$(NDKPREFIX)/arm-linux-androideabi-strip
-CC=$(NDKPREFIX)/armv7a-linux-androideabi21-clang
+CC=$(NDKPREFIX)/armv7a-linux-androideabi$(PLATFORM)-clang
 CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC
 O=o
 OS=posix
--- a/Make.android-arm64
+++ b/Make.android-arm64
@@ -1,7 +1,5 @@
 # Android
-SDKPREFIX=$(HOME)/Android/Sdk
-NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
-JAVA_HOME=/usr
+include $(ROOT)/Make.android.config
 
 PTHREAD=-pthread
 AR=$(NDKPREFIX)/aarch64-linux-android-ar
@@ -8,7 +6,7 @@
 AS=$(NDKPREFIX)/aarch64-linux-android-as
 RANLIB=$(NDKPREFIX)/aarch64-linux-android-ranlib
 STRIP=$(NDKPREFIX)/aarch64-linux-android-strip
-CC=$(NDKPREFIX)/aarch64-linux-android21-clang
+CC=$(NDKPREFIX)/aarch64-linux-android$(PLATFORM)-clang
 CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -Dmain=dt_main -fPIC
 O=o
 OS=posix
--- /dev/null
+++ b/Make.android.config
@@ -1,0 +1,6 @@
+SDKPREFIX=$(HOME)/Android/Sdk
+JAVA_HOME=/usr
+BUILDTOOLS=30.0.3
+PLATFORM=21
+NDKPREFIX=$(SDKPREFIX)/ndk/21.1.6352462/toolchains/llvm/prebuilt/linux-x86_64/bin
+
--- a/Makefile
+++ b/Makefile
@@ -36,7 +36,7 @@
 	$(CC) $(CFLAGS) $*.c
 
 clean:
-	rm -f *.o */*.o */*.a *.a drawterm drawterm.exe
+	rm -f *.o */*.o */*/*.o */*.a *.a drawterm drawterm.exe
 
 kern/libkern.a:
 	(cd kern; $(MAKE))
--- a/README
+++ b/README
@@ -7,7 +7,7 @@
 
 
 INSTALLATION
---------------
+------------
 To build on Unix, run CONF=unix make.
 
 To build on Solaris using Sun cc, run CONF=sun make.
@@ -18,15 +18,16 @@
 
 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
+To build for Android, make sure Make.android.config is 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.
 
 
--- a/cpu.c
+++ b/cpu.c
@@ -243,7 +243,7 @@
 void
 usage(void)
 {
-	fprint(2, "usage: %s [-GBO] "
+	fprint(2, "usage: %s [-GBORC] "
 		"[-h host] [-u user] [-a authserver] [-s secstore] "
 		"[-e 'crypt hash'] [-k keypattern] "
 		"[-p] [-t timeout] "
@@ -260,8 +260,13 @@
 void
 cpumain(int argc, char **argv)
 {
-	char *s;
+	char *s, *root;
+	int bindcmd, bindroot;
 
+	bindroot = 1;
+	root = nil;
+	bindcmd = 1;
+
 	user = getenv("USER");
 	if((pass = getenv("PASS")) != nil)
 		remove("/env/PASS");
@@ -305,11 +310,8 @@
 		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);
+		root = smprint("/root/%s", EARGF(usage()));
+		cleanname(root);
 		break;
 	case 'c':
 		cmd = estrdup(EARGF(usage()));
@@ -325,9 +327,28 @@
 			*/
 		geometry = EARGF(usage());
 		break;
+	case 'R':
+		bindroot = 0;
+		break;
+	case 'C':
+		bindcmd = 0;
+		break;
 	default:
 		usage();
 	}ARGEND;
+
+	if (bindcmd)
+		bind("#C", "/", MAFTER);
+
+	if (bindroot || (root != nil))
+		if(bind("#U", "/root", MREPL) < 0)
+			panic("bind #U: %r");
+
+	if (root != nil) {
+		if(bind(root, "/root", MREPL) < 0)
+			panic("bind /root: %r");
+		free(root);
+	}
 
 	if(argc != 0)
 		usage();
--- a/drawterm.1
+++ b/drawterm.1
@@ -6,7 +6,7 @@
 .SH SYNOPSIS
 .B drawterm
 [
-.B -GBO
+.B -GBORC
 ] [
 .B -h
 .I host
@@ -64,6 +64,22 @@
 .IR cpu (1)
 to connect to the cpu server rather than 
 .IR rcpu (1)\fR.
+
+.TP
+.B -R
+Do not bind terminal root at
+.I /mnt/term/root
+unless
+.B -r \fIroot
+is also specified.
+
+.TP
+.B -C
+Do not bind
+.I /mnt/term/cmd
+for
+.IR os (1)
+command.
 
 .TP
 .B -h \fIhost
--- a/gui-android/Makefile
+++ b/gui-android/Makefile
@@ -1,5 +1,6 @@
 ROOT=..
 include ../Make.config
+include ../Make.android.config
 LIB=libgui.a
 
 OFILES=\
@@ -13,11 +14,11 @@
 	$(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
+	$(SDKPREFIX)/build-tools/$(BUILDTOOLS)/aapt package -f -m -M AndroidManifest.xml -I $(SDKPREFIX)/platforms/android-$(PLATFORM)/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/
+	$(SDKPREFIX)/build-tools/$(BUILDTOOLS)/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
+	$(JAVA_HOME)/bin/javac -d obj/ -classpath $(SDKPREFIX)/platforms/android-$(PLATFORM)/android.jar -sourcepath java java/org/echoline/drawterm/*.java gen/org/echoline/drawterm/R.java
 
--- a/gui-android/cpp/android.c
+++ b/gui-android/cpp/android.c
@@ -228,3 +228,15 @@
 	cpubody();
 }
 
+int
+titleread(char *buf, int n)
+{
+	return 0;
+}
+
+int
+titlewrite(char *buf, int n)
+{
+	return n;
+}
+
--- a/gui-android/cpp/devandroid.c
+++ b/gui-android/cpp/devandroid.c
@@ -24,10 +24,19 @@
 	Qcam		= 1,
 	Qaccel		= 2,
 	Qcompass	= 4,
-	Qnotification	= 6,
+	Qnotify		= 6,
 };
-#define QID(p, c, y) 	(((p)<<16) | ((c)<<4) | (y))
 
+Dirtab
+androiddir[] =
+{
+	".",		{Qdir, 0, QTDIR},	0,	DMDIR|0555,
+	"camNNNN.jpg",	{Qcam},			0,	0444,
+	"accel",	{Qaccel},		0,	0444,
+	"compass",	{Qcompass},		0,	0444,
+	"notify",	{Qnotify},		0,	0222,
+};
+
 static void androidinit(void);
 
 static void
@@ -41,14 +50,7 @@
 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;
+	return devattach('N', param);
 }
 
 static int
@@ -57,32 +59,33 @@
 	Qid q;
 
 	if (s == DEVDOTDOT) {
-		mkqid(&q, Qdir, 0, QTDIR);
-		devdir(c, q, "#N", 0, eve, 0555, dp);
+		devdir(c, d->qid, "#N", 0, eve, 0555, dp);
 		return 1;
 	}
 	if (s < Ncameras) {
+		d += 1;
+		q = d->qid;
+		q.path |= (s << 16);
 		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) {
+		d += 2;
 		sprintf(up->genbuf, "accel");
-		mkqid(&q, Qaccel, 0, QTFILE);
-		devdir(c, q, up->genbuf, 0, eve, 0444, dp);
+		devdir(c, d->qid, up->genbuf, 0, eve, 0444, dp);
 		return 1;
 	}
 	if (s == (Ncameras+1)) {
+		d += 3;
 		sprintf(up->genbuf, "compass");
-		mkqid(&q, Qcompass, 0, QTFILE);
-		devdir(c, q, up->genbuf, 0, eve, 0444, dp);
+		devdir(c, d->qid, 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);
+		d += 4;
+		sprintf(up->genbuf, "notify");
+		devdir(c, d->qid, up->genbuf, 0, eve, 0222, dp);
 		return 1;
 	}
 	return -1;
@@ -91,13 +94,13 @@
 static Walkqid*
 androidwalk(Chan *c, Chan *nc, char **name, int nname)
 {
-	return devwalk(c, nc, name, nname, 0, 0, androidgen);
+	return devwalk(c, nc, name, nname, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
 }
 
 static int
 androidstat(Chan *c, uchar *db, int n)
 {
-	return devstat(c, db, n, 0, 0, androidgen);
+	return devstat(c, db, n, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
 }
 
 static Chan*
@@ -105,7 +108,7 @@
 {
 	p9_uvlong s;
 
-	c = devopen(c, omode, 0, 0, androidgen);
+	c = devopen(c, omode, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
 
 	if (c->qid.path & Qcam) {
 		s = c->qid.path >> 16;
@@ -114,7 +117,6 @@
 	c->mode = openmode(omode);
 	c->flag |= COPEN;
 	c->offset = 0;
-	c->iounit = 8192;
 
 	return c;
 }
@@ -201,7 +203,7 @@
 			ASensorManager_destroyEventQueue(sensorManager, queue);
 			return l;
 		case Qdir:
-			return devdirread(c, a, n, 0, 0, androidgen);
+			return devdirread(c, a, n, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
 	}
 }
 
@@ -212,7 +214,7 @@
 	char *str;
 
 	switch((ulong)c->qid.path) {
-		case Qnotification:
+		case Qnotify:
 			str = malloc(n+1);
 			memcpy(str, a, n);
 			str[n] = '\0';
--- a/gui-android/java/org/echoline/drawterm/MainActivity.java
+++ b/gui-android/java/org/echoline/drawterm/MainActivity.java
@@ -30,6 +30,7 @@
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.TextView;
+import android.widget.CheckBox;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.hardware.camera2.CameraManager;
@@ -50,6 +51,7 @@
 import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 public class MainActivity extends Activity {
 	private Map<String, ?> map;
@@ -172,8 +174,11 @@
 		((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]);
+		((EditText)findViewById(R.id.passWord)).setText((String)a[3]);
+
+		((CheckBox)findViewById(R.id.aan)).setChecked(((String)a[4]).equals("true") ? true : false);
+		((CheckBox)findViewById(R.id.cmd)).setChecked(((String)a[5]).equals("true") ? true : false);
+		((CheckBox)findViewById(R.id.root)).setChecked(((String)a[6]).equals("true") ? true : false);
 	}
 
 	public void populateServers(Context context) {
@@ -253,10 +258,13 @@
 				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 aan = ((CheckBox)findViewById(R.id.aan)).isChecked() ? "true" : "false";
+				String cmd = ((CheckBox)findViewById(R.id.cmd)).isChecked() ? "true" : "false";
+				String root = ((CheckBox)findViewById(R.id.root)).isChecked() ? "true" : "false";
 
 				SharedPreferences settings = getSharedPreferences("DrawtermPrefs", 0);
 				SharedPreferences.Editor editor = settings.edit();
-				editor.putString(user + "@" + cpu + " (auth="  + auth + ")", cpu + "\007" + auth + "\007" + user + "\007" + pass);
+				editor.putString(user + "@" + cpu + " (auth="  + auth + ")", cpu + "\007" + auth + "\007" + user + "\007" + pass + "\007" + aan + "\007" + cmd + "\007" + root);
 				editor.commit();
 			}
 		});
@@ -263,6 +271,12 @@
 
 		button = (Button) findViewById(R.id.connect);
 		button.setOnClickListener(new View.OnClickListener() {
+			private String[] appendString(String []args, String s) {
+				String ret[] = Arrays.copyOf(args, args.length + 1);
+				ret[ret.length - 1] = s;
+				return ret;
+			}
+
 			@Override
 			public void onClick(final View view) {
 				String cpu = ((EditText)findViewById(R.id.cpuServer)).getText().toString();
@@ -270,7 +284,13 @@
 				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};
+				String args[] = {"drawterm", "-h", cpu, "-a", auth, "-u", user};
+				if (((CheckBox)findViewById(R.id.aan)).isChecked())
+					args = appendString(args, "-p");
+				if (!((CheckBox)findViewById(R.id.cmd)).isChecked())
+					args = appendString(args, "-C");
+				if (!((CheckBox)findViewById(R.id.root)).isChecked())
+					args = appendString(args, "-R");
 				runDrawterm(args, pass);
 			}
 		});
--- a/gui-android/res/layout/server_main.xml
+++ b/gui-android/res/layout/server_main.xml
@@ -39,6 +39,27 @@
             android:password="true"
             android:hint="Password"/>
 
+        <CheckBox android:id="@+id/aan"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ems="10"
+            android:checked="true"
+            android:text="AAN" />
+
+        <CheckBox android:id="@+id/root"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ems="10"
+            android:checked="true"
+            android:text="Local Files" />
+
+        <CheckBox android:id="@+id/cmd"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:ems="10"
+            android:checked="true"
+            android:text="Local Commands" />
+
         <Button
             android:id="@+id/save"
             android:layout_width="match_parent"
--- a/gui-cocoa/screen.m
+++ b/gui-cocoa/screen.m
@@ -206,6 +206,17 @@
 	});
 }
 
+int
+titleread(char *buf, int n)
+{
+	return 0;
+}
+
+int
+titlewrite(char *buf, int n)
+{
+	return n;
+}
 
 @implementation AppDelegate
 
--- a/gui-fbdev/fbdev.c
+++ b/gui-fbdev/fbdev.c
@@ -666,8 +666,15 @@
 	qunlock(&drawlock);
 }
 
-void
-titlewrite(char* buf)
+int
+titleread(char *buf, int n)
 {
+	return 0;
+}
+
+int
+titlewrite(char* buf, int n)
+{
+	return n;
 }
 
--- a/gui-osx/screen.c
+++ b/gui-osx/screen.c
@@ -753,3 +753,16 @@
 {
 	cpubody();
 }
+
+int
+titleread(char *buf, int n)
+{
+	return 0;
+}
+
+int
+titlewrite(char *buf, int n)
+{
+	return n;
+}
+
--- a/gui-win32/screen.c
+++ b/gui-win32/screen.c
@@ -687,3 +687,16 @@
 {
 	cpubody();
 }
+
+int
+titleread(char *buf, int n)
+{
+	return 0;
+}
+
+int
+titlewrite(char *buf, int n)
+{
+	return n;
+}
+
--- a/gui-x11/x11.c
+++ b/gui-x11/x11.c
@@ -1266,3 +1266,24 @@
 {
 	cpubody();
 }
+
+int
+titleread(char *buf, int n)
+{
+	char *title;
+	XFetchName(xdisplay, xdrawable, &title);
+	memcpy(buf, title, n);
+	XFree(title);
+	return n;
+}
+
+int
+titlewrite(char *buf, int n)
+{
+	char *title = malloc((n+1) * sizeof(char));
+	memcpy(title, buf, n);
+	title[n] = '\0';
+	XStoreName(xdisplay, xdrawable, title);
+	free(title);
+	return n;
+}
--- a/kern/devaudio-alsa.c
+++ b/kern/devaudio-alsa.c
@@ -76,16 +76,19 @@
 audiodevwrite(void *v, int n)
 {
 	snd_pcm_sframes_t frames;
-	int tot, m;
+	int tot, m, fr;
 
 	for(tot = 0; tot < n; tot += m){
+		fr = (n-tot)/4;
 		do {
-			frames = snd_pcm_writei(playback, v+tot, (n-tot)/4);
-		} while(frames == -EAGAIN);
+			frames = snd_pcm_writei(playback, v+tot, fr);
+			if (frames < 0 && snd_pcm_recover(playback, frames, 0) == 0)
+				frames = fr;
+			if (frames < 0)
+				break;
+		} while(frames != fr);
 		if (frames < 0)
-			frames = snd_pcm_recover(playback, frames, 0);
-		if (frames < 0)
-			error((char*)snd_strerror(frames));
+			error("snd_pcm_writei");
 		m = frames*4;
 	}
 
@@ -100,9 +103,11 @@
 	do {
 		frames = snd_pcm_readi(capture, v, n/4);
 	} while(frames == -EAGAIN);
-
+	if (frames < 0 && snd_pcm_recover(capture, frames, 0) == 0)
+		frames = n/4;
 	if (frames < 0)
-		error((char*)snd_strerror(frames));
+		error("snd_pcm_readi");
 
 	return frames*4;
 }
+
--- a/kern/devaudio.c
+++ b/kern/devaudio.c
@@ -14,6 +14,7 @@
 	Aclosed		= 0,
 	Aread,
 	Awrite,
+	Ardwr,
 
 	Speed		= 44100,
 	Ncmd		= 50,		/* max volume command words */
@@ -31,7 +32,7 @@
 {
 	QLock	lk;
 	Rendez	vous;
-	int	amode;		/* Aclosed/Aread/Awrite for /audio */
+	int	amode;		/* Aclosed/Aread/Awrite/Ardwr for /audio */
 } audio;
 
 #define aqlock(a) qlock(&(a)->lk)
@@ -114,6 +115,8 @@
 		amode = Awrite;
 		if((omode&7) == OREAD)
 			amode = Aread;
+		else if((omode&7) == ORDWR)
+			amode = Ardwr;
 		aqlock(&audio);
 		if(waserror()){
 			aqunlock(&audio);
@@ -178,7 +181,7 @@
 		return devdirread(c, a, n, audiodir, nelem(audiodir), devgen);
 
 	case Qaudio:
-		if(audio.amode != Aread)
+		if(audio.amode != Aread && audio.amode != Ardwr)
 			error(Emode);
 		aqlock(&audio);
 		if(waserror()){
@@ -324,7 +327,7 @@
 		break;
 
 	case Qaudio:
-		if(audio.amode != Awrite)
+		if(audio.amode != Awrite && audio.amode != Ardwr)
 			error(Emode);
 		aqlock(&audio);
 		if(waserror()){
--- a/kern/devcons.c
+++ b/kern/devcons.c
@@ -346,6 +346,7 @@
 	Qsysstat,
 	Qtime,
 	Qzero,
+	Qlabel,
 };
 
 enum
@@ -373,6 +374,7 @@
 	"sysstat",	{Qsysstat},	0,		0666,
 	"time",		{Qtime},	NUMSIZE+3*VLNUMSIZE,	0664,
 	"zero",		{Qzero},	0,		0444,
+	"label",	{Qlabel},	0, 		0666,
 };
 
 Dirtab *snarftab = &consdir[Qsnarf];
@@ -652,6 +654,12 @@
 		memset(buf, 0, n);
 		return n;
 
+	case Qlabel:
+		if (n > sizeof tmp)
+			n = sizeof tmp;
+		n = titleread(tmp, n);
+		return readstr((ulong)offset, buf, n, tmp);
+
 	case Qosversion:
 		snprint(tmp, sizeof tmp, "2000");
 		n = readstr((ulong)offset, buf, n, tmp);
@@ -784,6 +792,10 @@
 		if(buf[n-1] == '\n')
 			buf[n-1] = 0;
 		kstrdup(&sysname, buf);
+		break;
+
+	case Qlabel:
+		titlewrite(a, n);
 		break;
 
 	default:
--- a/kern/devtab.c
+++ b/kern/devtab.c
@@ -19,6 +19,9 @@
 extern Dev kbddevtab;
 extern Dev cmddevtab;
 extern Dev envdevtab;
+#ifdef __ANDROID__
+extern Dev androiddevtab;
+#endif
 
 Dev *devtab[] = {
 	&rootdevtab,
@@ -36,6 +39,9 @@
 	&kbddevtab,
 	&cmddevtab,
 	&envdevtab,
+#ifdef __ANDROID__
+	&androiddevtab,
+#endif
 	0
 };
 
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -227,3 +227,5 @@
 void	screeninit(void);
 extern	void	terminit(void);
 extern	void	setterm(int);
+int		titleread(char*, int);
+int		titlewrite(char*, int);
--- a/main.c
+++ b/main.c
@@ -51,11 +51,10 @@
 		panic("bind #e: %r");
 	if(bind("#I", "/net", MBEFORE) < 0)
 		panic("bind #I: %r");
-	if(bind("#U", "/root", MREPL) < 0)
-		panic("bind #U: %r");
 	bind("#A", "/dev", MAFTER);
+#ifdef __ANDROID__
 	bind("#N", "/dev", MAFTER);
-	bind("#C", "/", MAFTER);
+#endif
 
 	if(open("/dev/cons", OREAD) != 0)
 		panic("open0: %r");