xref: /plan9/sys/src/libc/9sys/announce.c (revision da51d93a95fd527106ceeb0537961de9ab01e9ec)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <ctype.h>
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier static int	nettrans(char*, char*, int na, char*, int);
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier enum
87dd7cddfSDavid du Colombier {
97dd7cddfSDavid du Colombier 	Maxpath=	256,
107dd7cddfSDavid du Colombier };
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier /*
137dd7cddfSDavid du Colombier  *  announce a network service.
147dd7cddfSDavid du Colombier  */
157dd7cddfSDavid du Colombier int
announce(char * addr,char * dir)167dd7cddfSDavid du Colombier announce(char *addr, char *dir)
177dd7cddfSDavid du Colombier {
187dd7cddfSDavid du Colombier 	int ctl, n, m;
197dd7cddfSDavid du Colombier 	char buf[Maxpath];
207dd7cddfSDavid du Colombier 	char buf2[Maxpath];
217dd7cddfSDavid du Colombier 	char netdir[Maxpath];
227dd7cddfSDavid du Colombier 	char naddr[Maxpath];
237dd7cddfSDavid du Colombier 	char *cp;
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier 	/*
267dd7cddfSDavid du Colombier 	 *  translate the address
277dd7cddfSDavid du Colombier 	 */
287dd7cddfSDavid du Colombier 	if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
297dd7cddfSDavid du Colombier 		return -1;
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier 	/*
327dd7cddfSDavid du Colombier 	 * get a control channel
337dd7cddfSDavid du Colombier 	 */
347dd7cddfSDavid du Colombier 	ctl = open(netdir, ORDWR);
357dd7cddfSDavid du Colombier 	if(ctl<0){
367dd7cddfSDavid du Colombier 		werrstr("announce opening %s: %r", netdir);
377dd7cddfSDavid du Colombier 		return -1;
387dd7cddfSDavid du Colombier 	}
397dd7cddfSDavid du Colombier 	cp = strrchr(netdir, '/');
407dd7cddfSDavid du Colombier 	if(cp == nil){
417dd7cddfSDavid du Colombier 		werrstr("announce arg format %s", netdir);
427dd7cddfSDavid du Colombier 		close(ctl);
437dd7cddfSDavid du Colombier 		return -1;
447dd7cddfSDavid du Colombier 	}
457dd7cddfSDavid du Colombier 	*cp = 0;
467dd7cddfSDavid du Colombier 
477dd7cddfSDavid du Colombier 	/*
487dd7cddfSDavid du Colombier 	 *  find out which line we have
497dd7cddfSDavid du Colombier 	 */
507dd7cddfSDavid du Colombier 	n = snprint(buf, sizeof(buf), "%s/", netdir);
517dd7cddfSDavid du Colombier 	m = read(ctl, &buf[n], sizeof(buf)-n-1);
527dd7cddfSDavid du Colombier 	if(m <= 0){
537dd7cddfSDavid du Colombier 		werrstr("announce reading %s: %r", netdir);
547dd7cddfSDavid du Colombier 		close(ctl);
557dd7cddfSDavid du Colombier 		return -1;
567dd7cddfSDavid du Colombier 	}
577dd7cddfSDavid du Colombier 	buf[n+m] = 0;
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier 	/*
607dd7cddfSDavid du Colombier 	 *  make the call
617dd7cddfSDavid du Colombier 	 */
627dd7cddfSDavid du Colombier 	n = snprint(buf2, sizeof(buf2), "announce %s", naddr);
637dd7cddfSDavid du Colombier 	if(write(ctl, buf2, n)!=n){
647dd7cddfSDavid du Colombier 		werrstr("announce writing %s: %r", netdir);
657dd7cddfSDavid du Colombier 		close(ctl);
667dd7cddfSDavid du Colombier 		return -1;
677dd7cddfSDavid du Colombier 	}
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier 	/*
707dd7cddfSDavid du Colombier 	 *  return directory etc.
717dd7cddfSDavid du Colombier 	 */
727dd7cddfSDavid du Colombier 	if(dir){
737dd7cddfSDavid du Colombier 		strncpy(dir, buf, NETPATHLEN);
747dd7cddfSDavid du Colombier 		dir[NETPATHLEN-1] = 0;
757dd7cddfSDavid du Colombier 	}
767dd7cddfSDavid du Colombier 	return ctl;
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier 
797dd7cddfSDavid du Colombier /*
807dd7cddfSDavid du Colombier  *  listen for an incoming call
817dd7cddfSDavid du Colombier  */
827dd7cddfSDavid du Colombier int
listen(char * dir,char * newdir)837dd7cddfSDavid du Colombier listen(char *dir, char *newdir)
847dd7cddfSDavid du Colombier {
857dd7cddfSDavid du Colombier 	int ctl, n, m;
867dd7cddfSDavid du Colombier 	char buf[Maxpath];
877dd7cddfSDavid du Colombier 	char *cp;
887dd7cddfSDavid du Colombier 
897dd7cddfSDavid du Colombier 	/*
907dd7cddfSDavid du Colombier 	 *  open listen, wait for a call
917dd7cddfSDavid du Colombier 	 */
927dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf), "%s/listen", dir);
937dd7cddfSDavid du Colombier 	ctl = open(buf, ORDWR);
947dd7cddfSDavid du Colombier 	if(ctl < 0){
957dd7cddfSDavid du Colombier 		werrstr("listen opening %s: %r", buf);
967dd7cddfSDavid du Colombier 		return -1;
977dd7cddfSDavid du Colombier 	}
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier 	/*
1007dd7cddfSDavid du Colombier 	 *  find out which line we have
1017dd7cddfSDavid du Colombier 	 */
1027dd7cddfSDavid du Colombier 	strncpy(buf, dir, sizeof(buf) - 1);
1037dd7cddfSDavid du Colombier 	buf[sizeof(buf) - 1] = 0;
1047dd7cddfSDavid du Colombier 	cp = strrchr(buf, '/');
1057dd7cddfSDavid du Colombier 	if(cp == nil){
1067dd7cddfSDavid du Colombier 		close(ctl);
1077dd7cddfSDavid du Colombier 		werrstr("listen arg format %s", dir);
1087dd7cddfSDavid du Colombier 		return -1;
1097dd7cddfSDavid du Colombier 	}
1107dd7cddfSDavid du Colombier 	*++cp = 0;
1117dd7cddfSDavid du Colombier 	n = cp-buf;
1127dd7cddfSDavid du Colombier 	m = read(ctl, cp, sizeof(buf) - n - 1);
1137dd7cddfSDavid du Colombier 	if(m <= 0){
1147dd7cddfSDavid du Colombier 		close(ctl);
1157dd7cddfSDavid du Colombier 		werrstr("listen reading %s/listen: %r", dir);
1167dd7cddfSDavid du Colombier 		return -1;
1177dd7cddfSDavid du Colombier 	}
1187dd7cddfSDavid du Colombier 	buf[n+m] = 0;
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier 	/*
1217dd7cddfSDavid du Colombier 	 *  return directory etc.
1227dd7cddfSDavid du Colombier 	 */
1237dd7cddfSDavid du Colombier 	if(newdir){
1247dd7cddfSDavid du Colombier 		strncpy(newdir, buf, NETPATHLEN);
1257dd7cddfSDavid du Colombier 		newdir[NETPATHLEN-1] = 0;
1267dd7cddfSDavid du Colombier 	}
1277dd7cddfSDavid du Colombier 	return ctl;
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier }
1307dd7cddfSDavid du Colombier 
1317dd7cddfSDavid du Colombier /*
1327dd7cddfSDavid du Colombier  *  accept a call, return an fd to the open data file
1337dd7cddfSDavid du Colombier  */
1347dd7cddfSDavid du Colombier int
accept(int ctl,char * dir)1357dd7cddfSDavid du Colombier accept(int ctl, char *dir)
1367dd7cddfSDavid du Colombier {
1377dd7cddfSDavid du Colombier 	char buf[Maxpath];
1387dd7cddfSDavid du Colombier 	char *num;
1397dd7cddfSDavid du Colombier 	long n;
1407dd7cddfSDavid du Colombier 
1417dd7cddfSDavid du Colombier 	num = strrchr(dir, '/');
1427dd7cddfSDavid du Colombier 	if(num == nil)
1437dd7cddfSDavid du Colombier 		num = dir;
1447dd7cddfSDavid du Colombier 	else
1457dd7cddfSDavid du Colombier 		num++;
1467dd7cddfSDavid du Colombier 
1477dd7cddfSDavid du Colombier 	n = snprint(buf, sizeof(buf), "accept %s", num);
1487dd7cddfSDavid du Colombier 	write(ctl, buf, n); /* ignore return value, network might not need accepts */
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf), "%s/data", dir);
1517dd7cddfSDavid du Colombier 	return open(buf, ORDWR);
1527dd7cddfSDavid du Colombier }
1537dd7cddfSDavid du Colombier 
1547dd7cddfSDavid du Colombier /*
1557dd7cddfSDavid du Colombier  *  reject a call, tell device the reason for the rejection
1567dd7cddfSDavid du Colombier  */
1577dd7cddfSDavid du Colombier int
reject(int ctl,char * dir,char * cause)1587dd7cddfSDavid du Colombier reject(int ctl, char *dir, char *cause)
1597dd7cddfSDavid du Colombier {
1607dd7cddfSDavid du Colombier 	char buf[Maxpath];
1617dd7cddfSDavid du Colombier 	char *num;
1627dd7cddfSDavid du Colombier 	long n;
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier 	num = strrchr(dir, '/');
1657dd7cddfSDavid du Colombier 	if(num == 0)
1667dd7cddfSDavid du Colombier 		num = dir;
1677dd7cddfSDavid du Colombier 	else
1687dd7cddfSDavid du Colombier 		num++;
1697dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf), "reject %s %s", num, cause);
1707dd7cddfSDavid du Colombier 	n = strlen(buf);
1717dd7cddfSDavid du Colombier 	if(write(ctl, buf, n) != n)
1727dd7cddfSDavid du Colombier 		return -1;
1737dd7cddfSDavid du Colombier 	return 0;
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier /*
1777dd7cddfSDavid du Colombier  *  perform the identity translation (in case we can't reach cs)
1787dd7cddfSDavid du Colombier  */
1797dd7cddfSDavid du Colombier static int
identtrans(char * netdir,char * addr,char * naddr,int na,char * file,int nf)1807dd7cddfSDavid du Colombier identtrans(char *netdir, char *addr, char *naddr, int na, char *file, int nf)
1817dd7cddfSDavid du Colombier {
1827dd7cddfSDavid du Colombier 	char proto[Maxpath];
1837dd7cddfSDavid du Colombier 	char *p;
1847dd7cddfSDavid du Colombier 
1857dd7cddfSDavid du Colombier 	USED(nf);
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier 	/* parse the protocol */
1887dd7cddfSDavid du Colombier 	strncpy(proto, addr, sizeof(proto));
1897dd7cddfSDavid du Colombier 	proto[sizeof(proto)-1] = 0;
1907dd7cddfSDavid du Colombier 	p = strchr(proto, '!');
1917dd7cddfSDavid du Colombier 	if(p)
1927dd7cddfSDavid du Colombier 		*p++ = 0;
1937dd7cddfSDavid du Colombier 
1947dd7cddfSDavid du Colombier 	snprint(file, nf, "%s/%s/clone", netdir, proto);
1957dd7cddfSDavid du Colombier 	strncpy(naddr, p, na);
1967dd7cddfSDavid du Colombier 	naddr[na-1] = 0;
1977dd7cddfSDavid du Colombier 
1987dd7cddfSDavid du Colombier 	return 1;
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier /*
2027dd7cddfSDavid du Colombier  *  call up the connection server and get a translation
2037dd7cddfSDavid du Colombier  */
2047dd7cddfSDavid du Colombier static int
nettrans(char * addr,char * naddr,int na,char * file,int nf)2057dd7cddfSDavid du Colombier nettrans(char *addr, char *naddr, int na, char *file, int nf)
2067dd7cddfSDavid du Colombier {
2077dd7cddfSDavid du Colombier 	int i, fd;
2087dd7cddfSDavid du Colombier 	char buf[Maxpath];
2097dd7cddfSDavid du Colombier 	char netdir[Maxpath];
2107dd7cddfSDavid du Colombier 	char *p, *p2;
2117dd7cddfSDavid du Colombier 	long n;
2127dd7cddfSDavid du Colombier 
2137dd7cddfSDavid du Colombier 	/*
2147dd7cddfSDavid du Colombier 	 *  parse, get network directory
2157dd7cddfSDavid du Colombier 	 */
2167dd7cddfSDavid du Colombier 	p = strchr(addr, '!');
2177dd7cddfSDavid du Colombier 	if(p == 0){
2187dd7cddfSDavid du Colombier 		werrstr("bad dial string: %s", addr);
2197dd7cddfSDavid du Colombier 		return -1;
2207dd7cddfSDavid du Colombier 	}
2217dd7cddfSDavid du Colombier 	if(*addr != '/'){
2227dd7cddfSDavid du Colombier 		strncpy(netdir, "/net", sizeof(netdir));
2237dd7cddfSDavid du Colombier 		netdir[sizeof(netdir) - 1] = 0;
2247dd7cddfSDavid du Colombier 	} else {
2257dd7cddfSDavid du Colombier 		for(p2 = p; *p2 != '/'; p2--)
2267dd7cddfSDavid du Colombier 			;
2277dd7cddfSDavid du Colombier 		i = p2 - addr;
2287dd7cddfSDavid du Colombier 		if(i == 0 || i >= sizeof(netdir)){
2297dd7cddfSDavid du Colombier 			werrstr("bad dial string: %s", addr);
2307dd7cddfSDavid du Colombier 			return -1;
2317dd7cddfSDavid du Colombier 		}
2327dd7cddfSDavid du Colombier 		strncpy(netdir, addr, i);
2337dd7cddfSDavid du Colombier 		netdir[i] = 0;
2347dd7cddfSDavid du Colombier 		addr = p2 + 1;
2357dd7cddfSDavid du Colombier 	}
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier 	/*
2387dd7cddfSDavid du Colombier 	 *  ask the connection server
2397dd7cddfSDavid du Colombier 	 */
2407dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf), "%s/cs", netdir);
2417dd7cddfSDavid du Colombier 	fd = open(buf, ORDWR);
2427dd7cddfSDavid du Colombier 	if(fd < 0)
2437dd7cddfSDavid du Colombier 		return identtrans(netdir, addr, naddr, na, file, nf);
2447dd7cddfSDavid du Colombier 	if(write(fd, addr, strlen(addr)) < 0){
2457dd7cddfSDavid du Colombier 		close(fd);
2467dd7cddfSDavid du Colombier 		return -1;
2477dd7cddfSDavid du Colombier 	}
2487dd7cddfSDavid du Colombier 	seek(fd, 0, 0);
2497dd7cddfSDavid du Colombier 	n = read(fd, buf, sizeof(buf)-1);
2507dd7cddfSDavid du Colombier 	close(fd);
2517dd7cddfSDavid du Colombier 	if(n <= 0)
2527dd7cddfSDavid du Colombier 		return -1;
2537dd7cddfSDavid du Colombier 	buf[n] = 0;
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier 	/*
2567dd7cddfSDavid du Colombier 	 *  parse the reply
2577dd7cddfSDavid du Colombier 	 */
2587dd7cddfSDavid du Colombier 	p = strchr(buf, ' ');
2597dd7cddfSDavid du Colombier 	if(p == 0)
2607dd7cddfSDavid du Colombier 		return -1;
2617dd7cddfSDavid du Colombier 	*p++ = 0;
2627dd7cddfSDavid du Colombier 	strncpy(naddr, p, na);
2637dd7cddfSDavid du Colombier 	naddr[na-1] = 0;
264*da51d93aSDavid du Colombier 
265*da51d93aSDavid du Colombier 	if(buf[0] == '/'){
266*da51d93aSDavid du Colombier 		p = strchr(buf+1, '/');
267*da51d93aSDavid du Colombier 		if(p == nil)
268*da51d93aSDavid du Colombier 			p = buf;
269*da51d93aSDavid du Colombier 		else
270*da51d93aSDavid du Colombier 			p++;
271*da51d93aSDavid du Colombier 	}
272*da51d93aSDavid du Colombier 	snprint(file, nf, "%s/%s", netdir, p);
2737dd7cddfSDavid du Colombier 	return 0;
2747dd7cddfSDavid du Colombier }
275