xref: /plan9/sys/src/cmd/samterm/plan9.c (revision e7d295677b9ada08eb7a196a06047fdf5d8dfea2)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <mouse.h>
67dd7cddfSDavid du Colombier #include <keyboard.h>
73e12c5d1SDavid du Colombier #include <frame.h>
87dd7cddfSDavid du Colombier #include <plumb.h>
93e12c5d1SDavid du Colombier #include "flayer.h"
103e12c5d1SDavid du Colombier #include "samterm.h"
113e12c5d1SDavid du Colombier 
12bd389b36SDavid du Colombier static char exname[64];
13bd389b36SDavid du Colombier 
143e12c5d1SDavid du Colombier void
usage(void)15*e7d29567SDavid du Colombier usage(void)
16*e7d29567SDavid du Colombier {
17*e7d29567SDavid du Colombier 	fprint(2, "usage: samterm [-a]\n");
18*e7d29567SDavid du Colombier 	threadexitsall("usage");
19*e7d29567SDavid du Colombier }
20*e7d29567SDavid du Colombier 
21*e7d29567SDavid du Colombier void
getscreen(int argc,char ** argv)223e12c5d1SDavid du Colombier getscreen(int argc, char **argv)
233e12c5d1SDavid du Colombier {
247dd7cddfSDavid du Colombier 	char *t;
257dd7cddfSDavid du Colombier 
26*e7d29567SDavid du Colombier 	ARGBEGIN{
27*e7d29567SDavid du Colombier 	case 'a':
28*e7d29567SDavid du Colombier 		autoindent = 1;
29*e7d29567SDavid du Colombier 		break;
30*e7d29567SDavid du Colombier 	default:
31*e7d29567SDavid du Colombier 		usage();
32*e7d29567SDavid du Colombier 	}ARGEND
33*e7d29567SDavid du Colombier 
347dd7cddfSDavid du Colombier 	if(initdraw(panic1, nil, "sam") < 0){
35*e7d29567SDavid du Colombier 		fprint(2, "samterm: initdraw: %r\n");
367dd7cddfSDavid du Colombier 		threadexitsall("init");
377dd7cddfSDavid du Colombier 	}
387dd7cddfSDavid du Colombier 	t = getenv("tabstop");
397dd7cddfSDavid du Colombier 	if(t != nil)
407dd7cddfSDavid du Colombier 		maxtab = strtoul(t, nil, 0);
417dd7cddfSDavid du Colombier 	draw(screen, screen->clipr, display->white, nil, ZP);
423e12c5d1SDavid du Colombier }
433e12c5d1SDavid du Colombier 
443e12c5d1SDavid du Colombier int
screensize(int * w,int * h)45219b2ee8SDavid du Colombier screensize(int *w, int *h)
46219b2ee8SDavid du Colombier {
47219b2ee8SDavid du Colombier 	int fd, n;
48219b2ee8SDavid du Colombier 	char buf[5*12+1];
49219b2ee8SDavid du Colombier 
50219b2ee8SDavid du Colombier 	fd = open("/dev/screen", OREAD);
51219b2ee8SDavid du Colombier 	if(fd < 0)
52219b2ee8SDavid du Colombier 		return 0;
53219b2ee8SDavid du Colombier 	n = read(fd, buf, sizeof(buf)-1);
54219b2ee8SDavid du Colombier 	close(fd);
55219b2ee8SDavid du Colombier 	if (n != sizeof(buf)-1)
56219b2ee8SDavid du Colombier 		return 0;
57219b2ee8SDavid du Colombier 	buf[n] = 0;
58219b2ee8SDavid du Colombier 	if (h) {
59219b2ee8SDavid du Colombier 		*h = atoi(buf+4*12)-atoi(buf+2*12);
60219b2ee8SDavid du Colombier 		if (*h < 0)
61219b2ee8SDavid du Colombier 			return 0;
62219b2ee8SDavid du Colombier 	}
63219b2ee8SDavid du Colombier 	if (w) {
64219b2ee8SDavid du Colombier 		*w = atoi(buf+3*12)-atoi(buf+1*12);
65219b2ee8SDavid du Colombier 		if (*w < 0)
66219b2ee8SDavid du Colombier 			return 0;
67219b2ee8SDavid du Colombier 	}
68219b2ee8SDavid du Colombier 	return 1;
69219b2ee8SDavid du Colombier }
70219b2ee8SDavid du Colombier 
71219b2ee8SDavid du Colombier int
snarfswap(char * fromsam,int nc,char ** tosam)723e12c5d1SDavid du Colombier snarfswap(char *fromsam, int nc, char **tosam)
733e12c5d1SDavid du Colombier {
743e12c5d1SDavid du Colombier 	char *s1;
757dd7cddfSDavid du Colombier 	int f, n, ss;
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier 	f = open("/dev/snarf", 0);
783e12c5d1SDavid du Colombier 	if(f < 0)
793e12c5d1SDavid du Colombier 		return -1;
807dd7cddfSDavid du Colombier 	ss = SNARFSIZE;
817dd7cddfSDavid du Colombier 	if(hversion < 2)
827dd7cddfSDavid du Colombier 		ss = 4096;
837dd7cddfSDavid du Colombier 	*tosam = s1 = alloc(ss);
847dd7cddfSDavid du Colombier 	n = read(f, s1, ss-1);
853e12c5d1SDavid du Colombier 	close(f);
863e12c5d1SDavid du Colombier 	if(n < 0)
873e12c5d1SDavid du Colombier 		n = 0;
88bd389b36SDavid du Colombier 	if (n == 0) {
893e12c5d1SDavid du Colombier 		*tosam = 0;
90bd389b36SDavid du Colombier 		free(s1);
91bd389b36SDavid du Colombier 	} else
923e12c5d1SDavid du Colombier 		s1[n] = 0;
933e12c5d1SDavid du Colombier 	f = create("/dev/snarf", 1, 0666);
943e12c5d1SDavid du Colombier 	if(f >= 0){
953e12c5d1SDavid du Colombier 		write(f, fromsam, nc);
963e12c5d1SDavid du Colombier 		close(f);
973e12c5d1SDavid du Colombier 	}
983e12c5d1SDavid du Colombier 	return n;
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier void
dumperrmsg(int count,int type,int count0,int c)1023e12c5d1SDavid du Colombier dumperrmsg(int count, int type, int count0, int c)
1033e12c5d1SDavid du Colombier {
1049a747e4fSDavid du Colombier 	fprint(2, "samterm: host mesg: count %d %ux %ux %ux %s...ignored\n",
1053e12c5d1SDavid du Colombier 		count, type, count0, c, rcvstring());
1063e12c5d1SDavid du Colombier }
107bd389b36SDavid du Colombier 
108bd389b36SDavid du Colombier void
removeextern(void)109bd389b36SDavid du Colombier removeextern(void)
110bd389b36SDavid du Colombier {
111bd389b36SDavid du Colombier 	remove(exname);
112bd389b36SDavid du Colombier }
113bd389b36SDavid du Colombier 
1147dd7cddfSDavid du Colombier Readbuf	hostbuf[2];
1157dd7cddfSDavid du Colombier Readbuf	plumbbuf[2];
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier void
extproc(void * argv)1187dd7cddfSDavid du Colombier extproc(void *argv)
1197dd7cddfSDavid du Colombier {
1207dd7cddfSDavid du Colombier 	Channel *c;
1217dd7cddfSDavid du Colombier 	int i, n, which, *fdp;
1227dd7cddfSDavid du Colombier 	void **arg;
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier 	arg = argv;
1257dd7cddfSDavid du Colombier 	c = arg[0];
1267dd7cddfSDavid du Colombier 	fdp = arg[1];
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier 	i = 0;
1297dd7cddfSDavid du Colombier 	for(;;){
1307dd7cddfSDavid du Colombier 		i = 1-i;	/* toggle */
1317dd7cddfSDavid du Colombier 		n = read(*fdp, plumbbuf[i].data, sizeof plumbbuf[i].data);
1327dd7cddfSDavid du Colombier 		if(n <= 0){
1339a747e4fSDavid du Colombier 			fprint(2, "samterm: extern read error: %r\n");
1347dd7cddfSDavid du Colombier 			threadexits("extern");	/* not a fatal error */
1357dd7cddfSDavid du Colombier 		}
1367dd7cddfSDavid du Colombier 		plumbbuf[i].n = n;
1377dd7cddfSDavid du Colombier 		which = i;
1387dd7cddfSDavid du Colombier 		send(c, &which);
1397dd7cddfSDavid du Colombier 	}
1407dd7cddfSDavid du Colombier }
1417dd7cddfSDavid du Colombier 
142bd389b36SDavid du Colombier void
extstart(void)143bd389b36SDavid du Colombier extstart(void)
144bd389b36SDavid du Colombier {
145bd389b36SDavid du Colombier 	char buf[32];
1467dd7cddfSDavid du Colombier 	int fd;
1477dd7cddfSDavid du Colombier 	static int p[2];
1487dd7cddfSDavid du Colombier 	static void *arg[2];
149bd389b36SDavid du Colombier 
150bd389b36SDavid du Colombier 	if(pipe(p) < 0)
151bd389b36SDavid du Colombier 		return;
152bd389b36SDavid du Colombier 	sprint(exname, "/srv/sam.%s", getuser());
153bd389b36SDavid du Colombier 	fd = create(exname, 1, 0600);
154219b2ee8SDavid du Colombier 	if(fd < 0){	/* assume existing guy is more important */
155bd389b36SDavid du Colombier     Err:
156bd389b36SDavid du Colombier 		close(p[0]);
157bd389b36SDavid du Colombier 		close(p[1]);
158bd389b36SDavid du Colombier 		return;
159bd389b36SDavid du Colombier 	}
160bd389b36SDavid du Colombier 	sprint(buf, "%d", p[0]);
161bd389b36SDavid du Colombier 	if(write(fd, buf, strlen(buf)) <= 0)
162bd389b36SDavid du Colombier 		goto Err;
163bd389b36SDavid du Colombier 	close(fd);
164bd389b36SDavid du Colombier 	/*
165bd389b36SDavid du Colombier 	 * leave p[0] open so if the file is removed the event
166bd389b36SDavid du Colombier 	 * library won't get an error
167bd389b36SDavid du Colombier 	 */
1687dd7cddfSDavid du Colombier 	plumbc = chancreate(sizeof(int), 0);
1697dd7cddfSDavid du Colombier 	arg[0] = plumbc;
1707dd7cddfSDavid du Colombier 	arg[1] = &p[1];
1717dd7cddfSDavid du Colombier 	proccreate(extproc, arg, 1024);
172bd389b36SDavid du Colombier 	atexit(removeextern);
173bd389b36SDavid du Colombier }
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier int
plumbformat(int i)1767dd7cddfSDavid du Colombier plumbformat(int i)
1777dd7cddfSDavid du Colombier {
1787dd7cddfSDavid du Colombier 	Plumbmsg *m;
1797dd7cddfSDavid du Colombier 	char *addr, *data, *act;
1807dd7cddfSDavid du Colombier 	int n;
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier 	data = (char*)plumbbuf[i].data;
1837dd7cddfSDavid du Colombier 	m = plumbunpack(data, plumbbuf[i].n);
1847dd7cddfSDavid du Colombier 	if(m == nil)
1857dd7cddfSDavid du Colombier 		return 0;
1867dd7cddfSDavid du Colombier 	n = m->ndata;
1877dd7cddfSDavid du Colombier 	if(n == 0){
1887dd7cddfSDavid du Colombier 		plumbfree(m);
1897dd7cddfSDavid du Colombier 		return 0;
1907dd7cddfSDavid du Colombier 	}
1917dd7cddfSDavid du Colombier 	act = plumblookup(m->attr, "action");
1927dd7cddfSDavid du Colombier 	if(act!=nil && strcmp(act, "showfile")!=0){
1937dd7cddfSDavid du Colombier 		/* can't handle other cases yet */
1947dd7cddfSDavid du Colombier 		plumbfree(m);
1957dd7cddfSDavid du Colombier 		return 0;
1967dd7cddfSDavid du Colombier 	}
1977dd7cddfSDavid du Colombier 	addr = plumblookup(m->attr, "addr");
1987dd7cddfSDavid du Colombier 	if(addr){
1997dd7cddfSDavid du Colombier 		if(addr[0] == '\0')
2007dd7cddfSDavid du Colombier 			addr = nil;
2017dd7cddfSDavid du Colombier 		else
2027dd7cddfSDavid du Colombier 			addr = strdup(addr);	/* copy to safe storage; we'll overwrite data */
2037dd7cddfSDavid du Colombier 	}
2047dd7cddfSDavid du Colombier 	memmove(data, "B ", 2);	/* we know there's enough room for this */
2057dd7cddfSDavid du Colombier 	memmove(data+2, m->data, n);
2067dd7cddfSDavid du Colombier 	n += 2;
2077dd7cddfSDavid du Colombier 	if(data[n-1] != '\n')
2087dd7cddfSDavid du Colombier 		data[n++] = '\n';
2097dd7cddfSDavid du Colombier 	if(addr != nil){
2107dd7cddfSDavid du Colombier 		if(n+strlen(addr)+1+1 <= READBUFSIZE)
2117dd7cddfSDavid du Colombier 			n += sprint(data+n, "%s\n", addr);
2127dd7cddfSDavid du Colombier 		free(addr);
2137dd7cddfSDavid du Colombier 	}
2147dd7cddfSDavid du Colombier 	plumbbuf[i].n = n;
2157dd7cddfSDavid du Colombier 	plumbfree(m);
2167dd7cddfSDavid du Colombier 	return 1;
2177dd7cddfSDavid du Colombier }
2187dd7cddfSDavid du Colombier 
2197dd7cddfSDavid du Colombier void
plumbproc(void * argv)2207dd7cddfSDavid du Colombier plumbproc(void *argv)
2217dd7cddfSDavid du Colombier {
2227dd7cddfSDavid du Colombier 	Channel *c;
2237dd7cddfSDavid du Colombier 	int i, n, which, *fdp;
2247dd7cddfSDavid du Colombier 	void **arg;
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier 	arg = argv;
2277dd7cddfSDavid du Colombier 	c = arg[0];
2287dd7cddfSDavid du Colombier 	fdp = arg[1];
2297dd7cddfSDavid du Colombier 
2307dd7cddfSDavid du Colombier 	i = 0;
2317dd7cddfSDavid du Colombier 	for(;;){
2327dd7cddfSDavid du Colombier 		i = 1-i;	/* toggle */
2337dd7cddfSDavid du Colombier 		n = read(*fdp, plumbbuf[i].data, READBUFSIZE);
2347dd7cddfSDavid du Colombier 		if(n <= 0){
2359a747e4fSDavid du Colombier 			fprint(2, "samterm: plumb read error: %r\n");
2367dd7cddfSDavid du Colombier 			threadexits("plumb");	/* not a fatal error */
2377dd7cddfSDavid du Colombier 		}
2387dd7cddfSDavid du Colombier 		plumbbuf[i].n = n;
2397dd7cddfSDavid du Colombier 		if(plumbformat(i)){
2407dd7cddfSDavid du Colombier 			which = i;
2417dd7cddfSDavid du Colombier 			send(c, &which);
2427dd7cddfSDavid du Colombier 		}
2437dd7cddfSDavid du Colombier 	}
2447dd7cddfSDavid du Colombier }
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier int
plumbstart(void)2477dd7cddfSDavid du Colombier plumbstart(void)
2487dd7cddfSDavid du Colombier {
2497dd7cddfSDavid du Colombier 	static int fd;
2507dd7cddfSDavid du Colombier 	static void *arg[2];
2517dd7cddfSDavid du Colombier 
2527dd7cddfSDavid du Colombier 	plumbfd = plumbopen("send", OWRITE|OCEXEC);	/* not open is ok */
2537dd7cddfSDavid du Colombier 	fd = plumbopen("edit", OREAD|OCEXEC);
2547dd7cddfSDavid du Colombier 	if(fd < 0)
2557dd7cddfSDavid du Colombier 		return -1;
2567dd7cddfSDavid du Colombier 	plumbc = chancreate(sizeof(int), 0);
2577dd7cddfSDavid du Colombier 	if(plumbc == nil){
2587dd7cddfSDavid du Colombier 		close(fd);
2597dd7cddfSDavid du Colombier 		return -1;
2607dd7cddfSDavid du Colombier 	}
2617dd7cddfSDavid du Colombier 	arg[0] =plumbc;
2627dd7cddfSDavid du Colombier 	arg[1] = &fd;
2637dd7cddfSDavid du Colombier 	proccreate(plumbproc, arg, 4096);
2647dd7cddfSDavid du Colombier 	return 1;
2657dd7cddfSDavid du Colombier }
2667dd7cddfSDavid du Colombier 
2677dd7cddfSDavid du Colombier void
hostproc(void * arg)2687dd7cddfSDavid du Colombier hostproc(void *arg)
2697dd7cddfSDavid du Colombier {
2707dd7cddfSDavid du Colombier 	Channel *c;
2717dd7cddfSDavid du Colombier 	int i, n, which;
2727dd7cddfSDavid du Colombier 
2737dd7cddfSDavid du Colombier 	c = arg;
2747dd7cddfSDavid du Colombier 
2757dd7cddfSDavid du Colombier 	i = 0;
2767dd7cddfSDavid du Colombier 	for(;;){
2777dd7cddfSDavid du Colombier 		i = 1-i;	/* toggle */
2787dd7cddfSDavid du Colombier 		n = read(0, hostbuf[i].data, sizeof hostbuf[i].data);
2797dd7cddfSDavid du Colombier 		if(n <= 0){
280cc81b63cSDavid du Colombier 			if(n==0){
281cc81b63cSDavid du Colombier 				if(exiting)
282cc81b63cSDavid du Colombier 					threadexits(nil);
283cc81b63cSDavid du Colombier 				werrstr("unexpected eof");
284cc81b63cSDavid du Colombier 			}
2859a747e4fSDavid du Colombier 			fprint(2, "samterm: host read error: %r\n");
2867dd7cddfSDavid du Colombier 			threadexitsall("host");
2877dd7cddfSDavid du Colombier 		}
2887dd7cddfSDavid du Colombier 		hostbuf[i].n = n;
2897dd7cddfSDavid du Colombier 		which = i;
2907dd7cddfSDavid du Colombier 		send(c, &which);
2917dd7cddfSDavid du Colombier 	}
2927dd7cddfSDavid du Colombier }
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier void
hoststart(void)2957dd7cddfSDavid du Colombier hoststart(void)
2967dd7cddfSDavid du Colombier {
2977dd7cddfSDavid du Colombier 	hostc = chancreate(sizeof(int), 0);
2987dd7cddfSDavid du Colombier 	proccreate(hostproc, hostc, 1024);
2997dd7cddfSDavid du Colombier }
300