Browse Source

boot: start screenconsole as a service posted to #s/screenconsole, mount it from boot.

New screenconsole usage:

`aux/screenconsole [-d dbgfile] [srvname]`

without srvname the mount fd will be posted to #s/screenconsole.
It allows multiple mounts and it will not exit after unmounts.

9/boot/boot.c mounts it and opens /dev/cons as 0, 1 and 2 for its own children.
9/boot/aux.c then uses fd0 for outin instead of readline from console.c
9/boot/console.c has been removed (as it's replaced by screenconsole)

Change-Id: Ia94bd56afa09bdc23b8ace3c5240dcab419943e8
Signed-off-by: Giacomo Tesio <giacomo@tesio.it>
Giacomo Tesio 8 years ago
parent
commit
3fa7ae7280

+ 3 - 0
lib/namespace

@@ -16,6 +16,9 @@ bind -a #κ /dev
 bind -a #u /dev
 bind -b #P /dev
 
+# screen console
+mount -b /srv/screenconsole /dev
+
 # mount points
 mount -a /srv/slashn /n
 mount -a /boot /bin

+ 0 - 1
rc/bin/cpurc

@@ -79,7 +79,6 @@ if(test -e /cfg/$sysname/cpustart)
 # From bootfs
 /boot/listen1 -t -v tcp!*!1522 /boot/pipeconsole /boot/rc -m /boot/rcmain -i &
 /boot/comconsole '#t/eia0' /boot/rc -m/boot/rcmain -i &
-exec /boot/screenconsole /boot/rc -m/boot/rcmain -i
 
 # echo `{date} $sysname >>/sys/log/boot
 exit ''

+ 1 - 43
sys/src/9/boot/aux.c

@@ -11,48 +11,6 @@
 #include <libc.h>
 #include <../boot/boot.h>
 
-int readline(char* bud, int len);
-
-/*
-int
-plumb(char *dir, char *dest, int *efd, char *here)
-{
-	char buf[128];
-	char name[128];
-	int n;
-
-	sprint(name, "%s/clone", dir);
-	efd[0] = open(name, ORDWR);
-	if(efd[0] < 0)
-		return -1;
-	n = read(efd[0], buf, sizeof(buf)-1);
-	if(n < 0){
-		close(efd[0]);
-		return -1;
-	}
-	buf[n] = 0;
-	sprint(name, "%s/%s/data", dir, buf);
-	if(here){
-		sprint(buf, "announce %s", here);
-		if(sendmsg(efd[0], buf) < 0){
-			close(efd[0]);
-			return -1;
-		}
-	}
-	sprint(buf, "connect %s", dest);
-	if(sendmsg(efd[0], buf) < 0){
-		close(efd[0]);
-		return -1;
-	}
-	efd[1] = open(name, ORDWR);
-	if(efd[1] < 0){
-		close(efd[0]);
-		return -1;
-	}
-	return efd[1];
-}
- */
-
 int
 sendmsg(int fd, char *msg)
 {
@@ -179,7 +137,7 @@ outin(char *prompt, char *def, int len)
 	} 
 	print("%s[%s]: ", prompt, *def ? def : "no default");
 	memset(buf, 0, sizeof buf);
-	n = readline(buf, sizeof buf);
+	n = read(0, buf, len);
 
 	if(cpuflag){
 		alarm(0);

+ 54 - 1
sys/src/9/boot/boot.c

@@ -25,6 +25,7 @@ int	bargc;
 
 static Method	*rootserver(char*);
 static void	usbinit(void);
+static void	startconsole(void);
 static void	kbmap(void);
 
 void
@@ -42,7 +43,11 @@ boot(int argc, char *argv[])
 
 	fmtinstall('r', errfmt);
 
-	bind("#c", "/dev", MBEFORE);
+	/*
+	 *  start /dev/cons
+	 */
+	startconsole();
+
 	/*
 	 * init will reinitialize its namespace.
 	 * #ec gets us plan9.ini settings (*var variables).
@@ -275,6 +280,54 @@ usbinit(void)
 		run(usbd, nil);
 }
 
+static void
+startconsole(void)
+{
+	char *dbgfile, *argv[16], **av;
+	int i;
+	if(access("/boot/screenconsole", AEXEC) < 0)
+		fatal("cannot access /boot/screenconsole");
+
+	/* start agent */
+	i = 0;
+	av = argv;
+	av[i++] = "screenconsole";
+	if(dbgfile = getenv("debugconsole")){
+		av[i++] = "-d";
+		av[i++] = dbgfile;
+	}
+	av[i] = 0;
+	switch(fork()){
+	case -1:
+		fatal("starting screenconsole");
+	case 0:
+		exec("/boot/screenconsole", av);
+		fatal("execing /boot/screenconsole");
+	default:
+		break;
+	}
+
+	/* wait for agent to really be there */
+	while(access("#s/screenconsole", AEXIST) < 0){
+		sleep(250);
+	}
+	/* replace 0, 1 and 2 */
+	if((i = open("#s/screenconsole", ORDWR)) < 0)
+		fatal("open #s/screenconsole");
+	if(mount(i, -1, "/dev", MBEFORE, "", 'M') < 0)
+		fatal("mount /dev");
+	if((i = open("/dev/cons", OREAD))<0)
+		fatal("open /dev/cons, OREAD");
+	dup(i, 0);
+	close(i);
+	if((i = open("/dev/cons", OWRITE))<0)
+		fatal("open /dev/cons, OWRITE");
+	dup(i, 1);
+	close(i);
+	if(dup(1, 2) != 2)
+		fatal("dup(1, 2)");
+}
+
 static void
 kbmap(void)
 {

+ 0 - 1
sys/src/9/boot/boot.json

@@ -30,7 +30,6 @@
 		"bootcache.c",
 		"bootip.c",
 		"bootk8cpu.c",
-		"console.c",
 		"embed.c",
 		"local.c",
 		"paq.c",

+ 0 - 347
sys/src/9/boot/console.c

@@ -1,347 +0,0 @@
-#include <u.h>
-#include <libc.h>
-
-enum {
-	Spec =	0xF800,		/* Unicode private space */
-		PF =	Spec|0x20,	/* num pad function key */
-		View =	Spec|0x00,	/* view (shift window up) */
-		Shift =	Spec|0x60,
-		Break =	Spec|0x61,
-		Ctrl =	Spec|0x62,
-		Alt =	Spec|0x63,
-		Caps =	Spec|0x64,
-		Num =	Spec|0x65,
-		Middle =	Spec|0x66,
-		Altgr =	Spec|0x67,
-		Kmouse =	Spec|0x100,
-	No =	0x00,		/* peter */
-
-	KF =	0xF000,		/* function key (begin Unicode private space) */
-		Home =	KF|13,
-		Up =		KF|14,
-		Pgup =		KF|15,
-		Print =	KF|16,
-		Left =	KF|17,
-		Right =	KF|18,
-		End =	KF|24,
-		Down =	View,
-		Pgdown =	KF|19,
-		Ins =	KF|20,
-		Del =	0x7F,
-		Scroll =	KF|21,
-};
-
-typedef struct Keybscan Keybscan;
-struct Keybscan {
-	int esc1;
-	int esc2;
-	int alt;
-	int altgr;
-	int caps;
-	int ctl;
-	int num;
-	int shift;
-	int collecting;
-	int nk;
-	Rune kc[5];
-	int buttons;
-};
-
-static Keybscan kbscan;
-
-static Rune kbtab[256] =
-{
-[0x00]	No,	'\x1b',	'1',	'2',	'3',	'4',	'5',	'6',
-[0x08]	'7',	'8',	'9',	'0',	'-',	'=',	'\b',	'\t',
-[0x10]	'q',	'w',	'e',	'r',	't',	'y',	'u',	'i',
-[0x18]	'o',	'p',	'[',	']',	'\n',	Ctrl,	'a',	's',
-[0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
-[0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
-[0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	'*',
-[0x38]	Alt,	' ',	Ctrl,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
-[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	Scroll,	'7',
-[0x48]	'8',	'9',	'-',	'4',	'5',	'6',	'+',	'1',
-[0x50]	'2',	'3',	'0',	'.',	No,	No,	No,	KF|11,
-[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
-[0x60]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x68]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x70]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x78]	No,	View,	No,	Up,	No,	No,	No,	No,
-};
-
-static Rune kbtabshift[256] =
-{
-[0x00]	No,	'\x1b',	'!',	'@',	'#',	'$',	'%',	'^',
-[0x08]	'&',	'*',	'(',	')',	'_',	'+',	'\b',	'\t',
-[0x10]	'Q',	'W',	'E',	'R',	'T',	'Y',	'U',	'I',
-[0x18]	'O',	'P',	'{',	'}',	'\n',	Ctrl,	'A',	'S',
-[0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
-[0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
-[0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	'*',
-[0x38]	Alt,	' ',	Ctrl,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
-[0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	Scroll,	'7',
-[0x48]	'8',	'9',	'-',	'4',	'5',	'6',	'+',	'1',
-[0x50]	'2',	'3',	'0',	'.',	No,	No,	No,	KF|11,
-[0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
-[0x60]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x68]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x70]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x78]	No,	Up,	No,	Up,	No,	No,	No,	No,
-};
-
-static Rune kbtabesc1[256] =
-{
-[0x00]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x08]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x10]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x18]	No,	No,	No,	No,	'\n',	Ctrl,	No,	No,
-[0x20]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x28]	No,	No,	Shift,	No,	No,	No,	No,	No,
-[0x30]	No,	No,	No,	No,	No,	'/',	No,	Print,
-[0x38]	Altgr,	No,	No,	No,	No,	No,	No,	No,
-[0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
-[0x48]	Up,	Pgup,	No,	Left,	No,	Right,	No,	End,
-[0x50]	Down,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
-[0x58]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x60]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x68]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x70]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x78]	No,	Up,	No,	No,	No,	No,	No,	No,
-};
-
-static Rune kbtabaltgr[256] =
-{
-[0x00]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x08]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x10]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x18]	No,	No,	No,	No,	'\n',	Ctrl,	No,	No,
-[0x20]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x28]	No,	No,	Shift,	No,	No,	No,	No,	No,
-[0x30]	No,	No,	No,	No,	No,	'/',	No,	Print,
-[0x38]	Altgr,	No,	No,	No,	No,	No,	No,	No,
-[0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
-[0x48]	Up,	Pgup,	No,	Left,	No,	Right,	No,	End,
-[0x50]	Down,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
-[0x58]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x60]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x68]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x70]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x78]	No,	Up,	No,	No,	No,	No,	No,	No,
-};
-
-static Rune kbtabctrl[256] =
-{
-[0x00]	No,	'\x1b',	'\x11',	'\x12',	'\x13',	'\x14',	'\x15',	'\x16',
-[0x08]	'\x17',	'\x18',	'\x19',	'\x10',	'\n',	'\x1d',	'\b',	'\t',
-[0x10]	'\x11',	'\x17',	'\x05',	'\x12',	'\x14',	'\x19',	'\x15',	'\t',
-[0x18]	'\x0f',	'\x10',	'\x1b',	'\x1d',	'\n',	Ctrl,	'\x01',	'\x13',
-[0x20]	'\x04',	'\x06',	'\x07',	'\b',	'\n',	'\x0b',	'\x0c',	'\x1b',
-[0x28]	'\x07',	No,	Shift,	'\x1c',	'\x1a',	'\x18',	'\x03',	'\x16',
-[0x30]	'\x02',	'\x0e',	'\n',	'\x0c',	'\x0e',	'\x0f',	Shift,	'\n',
-[0x38]	Alt,	No,	Ctrl,	'\x05',	'\x06',	'\x07',	'\x04',	'\x05',
-[0x40]	'\x06',	'\x07',	'\x0c',	'\n',	'\x0e',	'\x05',	'\x06',	'\x17',
-[0x48]	'\x18',	'\x19',	'\n',	'\x14',	'\x15',	'\x16',	'\x0b',	'\x11',
-[0x50]	'\x12',	'\x13',	'\x10',	'\x0e',	No,	No,	No,	'\x0f',
-[0x58]	'\x0c',	No,	No,	No,	No,	No,	No,	No,
-[0x60]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x68]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x70]	No,	No,	No,	No,	No,	No,	No,	No,
-[0x78]	No,	'\x07',	No,	'\b',	No,	No,	No,	No,
-};
-
-int
-keybscan(uint8_t code, char *out, int len)
-{
-	Rune c;
-	int keyup;
-	int off;
-
-	c = code;
-	off = 0;
-
-	if(len < 16){
-		fprint(2, "keybscan: input buffer too short to be safe\n");
-		return -1;
-	}
-	if(c == 0xe0){
-		kbscan.esc1 = 1;
-		return off;
-	} else if(c == 0xe1){
-		kbscan.esc2 = 2;
-		return off;
-	}
-
-	keyup = c&0x80;
-	c &= 0x7f;
-	if(c > sizeof kbtab){
-		c |= keyup;
-		if(c != 0xFF)	/* these come fairly often: CAPSLOCK U Y */
-			fprint(2, "unknown key %ux\n", c);
-		return off;
-	}
-
-	if(kbscan.esc1){
-		c = kbtabesc1[c];
-		kbscan.esc1 = 0;
-	} else if(kbscan.esc2){
-		kbscan.esc2--;
-		return off;
-	} else if(kbscan.shift)
-		c = kbtabshift[c];
-	else if(kbscan.altgr)
-		c = kbtabaltgr[c];
-	else if(kbscan.ctl)
-		c = kbtabctrl[c];
-	else
-		c = kbtab[c];
-
-	if(kbscan.caps && c<='z' && c>='a')
-		c += 'A' - 'a';
-
-	/*
-	 *  keyup only important for shifts
-	 */
-	if(keyup){
-		switch(c){
-		case Alt:
-			kbscan.alt = 0;
-			break;
-		case Shift:
-			kbscan.shift = 0;
-			/*mouseshifted = 0;*/
-			break;
-		case Ctrl:
-			kbscan.ctl = 0;
-			break;
-		case Altgr:
-			kbscan.altgr = 0;
-			break;
-		case Kmouse|1:
-		case Kmouse|2:
-		case Kmouse|3:
-		case Kmouse|4:
-		case Kmouse|5:
-			kbscan.buttons &= ~(1<<(c-Kmouse-1));
-			/*if(kbdmouse)kbdmouse(kbscan.buttons);*/
-			break;
-		}
-		return off;
-	}
-
-	/*
-	 *  normal character
-	 */
-	if(!(c & (Spec|KF))){
-		off += runetochar(out+off, &c);
-		return off;
-	} else {
-		switch(c){
-		case Caps:
-			kbscan.caps ^= 1;
-			return off;
-		case Num:
-			kbscan.num ^= 1;
-			return off;
-		case Shift:
-			kbscan.shift = 1;
-			/*mouseshifted = 1;*/
-			return off;
-		case Alt:
-			kbscan.alt = 1;
-			/*
-			 * VMware and Qemu use Ctl-Alt as the key combination
-			 * to make the VM give up keyboard and mouse focus.
-			 * This has the unfortunate side effect that when you
-			 * come back into focus, Plan 9 thinks you want to type
-			 * a compose sequence (you just typed alt). 
-			 *
-			 * As a clumsy hack around this, we look for ctl-alt
-			 * and don't treat it as the start of a compose sequence.
-			 */
-			return off;
-		case Ctrl:
-			kbscan.ctl = 1;
-			return off;
-		case Altgr:
-			kbscan.altgr = 1;
-			return off;
-		case Kmouse|1:
-		case Kmouse|2:
-		case Kmouse|3:
-		case Kmouse|4:
-		case Kmouse|5:
-			kbscan.buttons |= 1<<(c-Kmouse-1);
-			/*if(kbdmouse)kbdmouse(kbscan.buttons);*/
-			return off;
-		}
-	}
-
-	off += runetochar(out+off, &c);
-	return off;
-
-}
-
-enum {
-	Black		= 0x00,
-	Blue		= 0x01,
-	Green		= 0x02,
-	Cyan		= 0x03,
-	Red		= 0x04,
-	Magenta		= 0x05,
-	Brown		= 0x06,
-	Grey		= 0x07,
-
-	Bright 		= 0x08,
-	Blinking	= 0x80,
-
-	Attr		= (Black<<4)|Grey,	/* (background<<4)|foreground */
-	Cursor = (Grey<<4)|Black,
-};
-
-enum {
-	Width		= 80*2,
-	Height		= 25,
-};
-
-int
-readline(char* buf, int buflen)
-{
-	int ps2fd;
-	int i, n, off, lastoff, len;
-	char* scan;
-	static uint8_t ibuf[32];
-
-	if((ps2fd = open("#P/ps2keyb", OREAD)) == -1){
-		errstr(buf, sizeof buf);
-		fprint(2, "open #P/ps2keyb: %s\n", buf);
-		return -1;
-	}
-
-	off = 0;
-	for (;;){
-		while((len = read(ps2fd, ibuf, sizeof ibuf)) > 0){
-			lastoff = off;
-			for(i = 0; i < len; i++){
-				if((n = keybscan(ibuf[i], buf+off, buflen - off)) == -1){
-					fprint(2, "keybscan -1\n");
-					return -1;
-				}
-				off += n;
-			}
-			if(buf[off-1] == '\n')
-				goto GotLine;
-			if(off > 0){
-				for(scan = buf + lastoff; scan < buf + off; scan++){
-					write(1, scan, 1);
-					if(*scan == 0x8)
-						off -= 2;
-				}
-			}
-		}
-	}
-GotLine:
-	close(ps2fd);
-	write(1, "\n", 1);
-	buf[off] = '\0';
-	return off - 1;
-}

+ 20 - 1
sys/src/cmd/aux/console/comconsole.c

@@ -44,6 +44,8 @@ opencom(char *file)
 void
 main(int argc, char *argv[])
 {
+	int fd, devmnt;
+
 	blind = 0;
 	linecontrol = 1;
 	crnl = 1;
@@ -60,5 +62,22 @@ main(int argc, char *argv[])
 
 	opencom(argv[0]);
 
-	servecons(++argv, passthrough, passthrough);
+	fd = servecons(passthrough, passthrough, &devmnt);
+
+	debug("%s %d: mounting cons for %s\n", argv0, getpid(), argv[0]);
+	if(mount(fd, -1, "/dev", MBEFORE, "", devmnt) == -1)
+		sysfatal("mount (%s): %r", argv[0]);
+
+	debug("%s (%d): all services started, ready to exec(%s)\n", argv0, getpid(), argv[0]);
+
+	/* become the requested program */
+	rfork(RFNOTEG|RFREND|RFCFDG);
+
+	fd = open("/dev/cons", OREAD);
+	fd = open("/dev/cons", OWRITE);
+	if(dup(fd, 2) != 2)
+		sysfatal("bad FDs: %r");
+
+	exec(argv[1], argv+1);
+	sysfatal("exec %s: %r", argv[1]);
 }

+ 5 - 1
sys/src/cmd/aux/console/console.h

@@ -27,6 +27,10 @@ enum
 /* Read from the first fd, do its own work, and write to the second */
 typedef void (*StreamFilter)(int, int);
 
+extern int systemwide;	/* all the system depend on this console:
+						 * - allow multiple attach
+						 * - never end fsserve
+						 */
 extern int blind;	/* no feedback for input, disables rawmode */
 extern int linecontrol;
 extern int crnl;	/* turn \n into \r\n to output device */
@@ -56,7 +60,7 @@ extern int blineready(Buffer *);
 #define bspace(b) (b->size - b->written)
 #define bpending(b) (b->written - b->read)
 
-extern void servecons(char *argv[], StreamFilter, StreamFilter);
+extern int servecons(StreamFilter, StreamFilter, int*);
 
 extern int fsinit(int *, int *);
 extern void fsserve(int, char*);

+ 19 - 1
sys/src/cmd/aux/console/pipeconsole.c

@@ -33,6 +33,8 @@ usage(void)
 void
 main(int argc, char *argv[])
 {
+	int fd, devmnt;
+
 	blind = 0;
 	linecontrol = 1;
 	crnl = 0;
@@ -53,5 +55,21 @@ main(int argc, char *argv[])
 	if(argc == 0)
 		usage();
 
-	servecons(argv, passthrough, passthrough);
+	fd = servecons(passthrough, passthrough, &devmnt);
+
+	debug("%s %d: mounting cons for %s\n", argv0, getpid(), argv[0]);
+	if(mount(fd, -1, "/dev", MBEFORE, "", devmnt) == -1)
+		sysfatal("mount (%s): %r", argv[0]);
+
+	debug("%s (%d): all services started, ready to exec(%s)\n", argv0, getpid(), argv[0]);
+
+	/* become the requested program */
+	rfork(RFNOTEG|RFREND|RFCFDG);
+
+	fd = open("/dev/cons", OREAD);
+	fd = open("/dev/cons", OWRITE);
+	if(dup(fd, 2) != 2)
+		sysfatal("bad FDs: %r");
+	exec(argv[0], argv);
+	sysfatal("exec %s: %r", argv[0]);
 }

+ 27 - 4
sys/src/cmd/aux/console/screenconsole.c

@@ -27,14 +27,31 @@ int crnl;
 static void
 usage(void)
 {
-	fprint(2, "usage: %s [-d dbgfile] program [args]\n", argv0);
+	fprint(2, "usage: %s [-d dbgfile] srvname\n", argv0);
 	exits("usage");
 }
+static void
+post(char *srv, int fd)
+{
+	int f;
+	char buf[128];
+
+	fprint(2, "post %s...\n", srv);
+	sprint(buf, "#s/%s", srv);
+	f = create(buf, OWRITE, 0666);
+	if(f < 0)
+		sysfatal("create(%s)", srv);
+	sprint(buf, "%d", fd);
+	if(write(f, buf, strlen(buf)) != strlen(buf))
+		sysfatal("write");
+}
 void
 main(int argc, char *argv[])
 {
-	int fd;
+	int fd, devmnt;
+	char *srv;
 
+	systemwide = 1; /* only screenconsole allows multiple attach */
 	blind = 0;
 	linecontrol = 1;
 	crnl = 0;
@@ -47,8 +64,12 @@ main(int argc, char *argv[])
 		break;
 	}ARGEND;
 
-	if(argc == 0)
+	if(argc > 1)
 		usage();
+	if(argc)
+		srv = argv[0];
+	else
+		srv = "screenconsole";
 
 	/* first try in /dev so that binding can work */
 	if((fd = open("/dev/ps2keyb", OREAD)) <= 0)
@@ -62,5 +83,7 @@ main(int argc, char *argv[])
 	dup(fd, 1);
 	close(fd);
 
-	servecons(argv, readkeyboard, writecga);
+	fd = servecons(readkeyboard, writecga, &devmnt);
+	post(srv, fd);
+	exits(0);
 }

+ 9 - 39
sys/src/cmd/aux/console/serve9p.c

@@ -35,6 +35,8 @@ typedef enum
 	Unmounted,		/* fsserve() loop while status < Unmounted */
 } Status;
 
+int systemwide;
+
 static Status status;
 static int rawmode;
 
@@ -209,7 +211,6 @@ struct OpQueue
 
 static OpQueue consreads;
 static AsyncOp *outputread;		/* only one process can access Qoutput */
-static AsyncOp *inputwrite;		/* only one process can access Qinput */
 
 static void
 qinit(OpQueue *q)
@@ -567,8 +568,8 @@ rattach(Fcall *req, Fcall *rep)
 	if(spec && spec[0])
 		return rerror(rep, "bad attach specifier");
 
-	if(external != nil){
-		/* we expect 3 valid Tattach:
+	if(external != nil && !systemwide){
+		/* when not system wide (aka screenconsole), we expect 3 valid Tattach:
 		 * 1 for the process that will send us the input, writing Qinput
 		 * 1 for the process that will print our output, reading Qoutput
 		 * 1 for the rest of the children
@@ -581,7 +582,7 @@ rattach(Fcall *req, Fcall *rep)
 	if(f == nil)
 		return rerror(rep, "out of memory");
 
-	if(input != nil && output != nil){
+	if(external == nil && input != nil && output != nil){
 		external = f;
 		status = Mounted;
 	}
@@ -822,7 +823,9 @@ rwrite(Fcall *req, Fcall *rep)
 			rep->count = req->count;
 			break;
 		case Qinput:
-			if(rawmode || blind){
+			if(ISCLOSED(outputfid) || status == Unmounted){
+				rep->count = 0;
+			} else if(rawmode || blind){
 				rep->count = bwrite(input, req->data, req->count);
 			} else if(!linecontrol) {
 				/* life is easy:
@@ -853,13 +856,6 @@ rwrite(Fcall *req, Fcall *rep)
 
 					/* we knew we have enough space, abort if not */
 					assert(maxlength == rep->count);
-				} else if(input->ctrld < input->size){
-					/* if this Twrite(Qinput) contains a ^D it has to
-					 * wait for a reply until someone consumed it
-					 */
-					assert(inputwrite == nil);
-					inputwrite = opalloc(req->tag, req->count);
-					return 0;
 				} else {
 					/* sync visible output and input buffer
 					 *
@@ -1006,32 +1002,6 @@ fsserve(int connection, char *owner)
 				break;
 			}
 		}
-		/* finally, if a Twrite(Qinput) is waiting for a reply we serve it.
-		 *
-		 * Note that Twrite(Qinput) are syncronous unless they activate
-		 * a input->ctrld, in which case they have to wait for a
-		 * Tread(Qcons) that deactivate the flag.
-		 * Moreover if the queue of consreads is empty after such
-		 * deactivation, we send a zero length Rwrite, so that it will
-		 * release the input device.
-		 */
-		debug("serve9p %d: if a Twrite(Qinput) is waiting for a reply we serve it. \n", fspid);
-		if(inputwrite && input->ctrld == input->size){
-			rep.type = Rwrite;
-			rep.tag = inputwrite->tag;
-			if(qempty((&consreads)))
-				rep.count = 0;
-			else
-				rep.count = inputwrite->count;
-
-			if((w = sendmessage(connection, &rep)) <= 0){
-				debug("serve9p %d: sendmessage for inputwrite returns %d\n", fspid, w);
-				break;
-			}
-
-			free(inputwrite);
-			inputwrite = nil;
-		}
 
 		/* We can exit (properly) only when the following conditions hold
 		 *
@@ -1053,7 +1023,7 @@ fsserve(int connection, char *owner)
 		 * (AND obviously if an unexpected error occurred)
 		 */
 	}
-	while(status < Unmounted || !ISCLOSED(inputfid) || !ISCLOSED(outputfid));
+	while(systemwide || status < Unmounted || !ISCLOSED(inputfid) || !ISCLOSED(outputfid));
 
 
 	if(r < 0)

+ 9 - 22
sys/src/cmd/aux/console/utils.c

@@ -109,11 +109,13 @@ gethostowner(void)
  *  - fd 0 can be read by inputFilter
  *  - fd 1 can be written by outputFilter
  *  - fd 2 can receive debug info (if debugging)
+ *
+ * returns the fd to mount
  */
-void
-servecons(char *argv[], StreamFilter inputFilter, StreamFilter outputFilter)
+int
+servecons(StreamFilter inputFilter, StreamFilter outputFilter, int *devmnt)
 {
-	int pid, input, output, fs, mnt, devmnt;
+	int pid, input, output, fs, mnt;
 	char *s;
 
 	s = gethostowner();
@@ -129,8 +131,7 @@ servecons(char *argv[], StreamFilter inputFilter, StreamFilter outputFilter)
 
 	debug("%s %d: started, linecontrol = %d, blind = %d\n", argv0, pid, linecontrol, blind);
 
-	fs = fsinit(&mnt, &devmnt);
-	debug("%s %d: fsinit: fs = %d, mnt = %d, devmnt = '%c'\n", argv0, pid, fs, mnt, devmnt);
+	fs = fsinit(&mnt, devmnt);
 
 	/* start the file system */
 	switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFCENVG|RFNOTEG|RFCNAMEG|RFFDG)){
@@ -162,7 +163,7 @@ servecons(char *argv[], StreamFilter inputFilter, StreamFilter outputFilter)
 			sysfatal("rfork (output writer): %r");
 			break;
 		case 0:
-			if(mount(mnt, -1, "/dev", MBEFORE, "", devmnt) == -1)
+			if(mount(mnt, -1, "/dev", MBEFORE, "", *devmnt) == -1)
 				sysfatal("mount (output writer): %r");
 			if((output = open("/dev/gconsout", OREAD)) == -1)
 				sysfatal("open /dev/gconsout: %r");
@@ -182,7 +183,7 @@ servecons(char *argv[], StreamFilter inputFilter, StreamFilter outputFilter)
 			sysfatal("rfork (input reader): %r");
 			break;
 		case 0:
-			if(mount(mnt, -1, "/dev", MBEFORE, "", devmnt) == -1)
+			if(mount(mnt, -1, "/dev", MBEFORE, "", *devmnt) == -1)
 				sysfatal("mount (input reader): %r");
 			if((input = open("/dev/gconsin", OWRITE)) == -1)
 				sysfatal("open /dev/gconsin: %r");
@@ -200,19 +201,5 @@ servecons(char *argv[], StreamFilter inputFilter, StreamFilter outputFilter)
 	close(0);
 	close(1);
 
-	debug("%s %d: mounting mnt for %s\n", argv0, pid, argv[0]);
-	if(mount(mnt, -1, "/dev", MBEFORE, "", devmnt) == -1)
-		sysfatal("mount (%s): %r", argv[0]);
-
-	debug("%s (%d): all services started, ready to exec(%s)\n", argv0, pid, argv[0]);
-
-	/* become the requested program */
-	rfork(RFNOTEG|RFREND|RFCFDG);
-
-	input = open("/dev/cons", OREAD);
-	output = open("/dev/cons", OWRITE);
-	if(dup(output, 2) != 2)
-		sysfatal("bad FDs (%d, %d): %r", input, output);
-
-	exec(argv[0], argv);
+	return mnt;
 }

+ 1 - 1
sys/src/cmd/init.c

@@ -182,7 +182,7 @@ rcexec(void)
 	if(cmd)
 		execl("/bin/rc", "rc", "-c", cmd, nil);
 	else if(manual || iscpu){
-		execl("/boot/screenconsole", "screenconsole", "/boot/rc", "-m/boot/rcmain", "-i", nil);
+		execl("/boot/rc", "rc", "-m/boot/rcmain", "-i", nil);
 	}else if(strcmp(service, "terminal") == 0)
 		execl("/bin/rc", "rc", "-c", ". /rc/bin/termrc; home=/usr/$user; cd; . lib/profile", nil);
 	else