xref: /plan9/sys/src/cmd/unix/drawterm/posix-factotum.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <sys/socket.h>
3*8ccd4a63SDavid du Colombier #include <sys/un.h>
4*8ccd4a63SDavid du Colombier #include <ctype.h>
5*8ccd4a63SDavid du Colombier #include <pwd.h>
6*8ccd4a63SDavid du Colombier #include <libc.h>
7*8ccd4a63SDavid du Colombier #include <auth.h>
8*8ccd4a63SDavid du Colombier #include <fcall.h>
9*8ccd4a63SDavid du Colombier #include <authsrv.h>
10*8ccd4a63SDavid du Colombier #include <libsec.h>
11*8ccd4a63SDavid du Colombier #include "drawterm.h"
12*8ccd4a63SDavid du Colombier 
13*8ccd4a63SDavid du Colombier #undef socket
14*8ccd4a63SDavid du Colombier #undef connect
15*8ccd4a63SDavid du Colombier #undef getenv
16*8ccd4a63SDavid du Colombier #undef access
17*8ccd4a63SDavid du Colombier 
18*8ccd4a63SDavid du Colombier char*
getuser(void)19*8ccd4a63SDavid du Colombier getuser(void)
20*8ccd4a63SDavid du Colombier {
21*8ccd4a63SDavid du Colombier 	static char user[64];
22*8ccd4a63SDavid du Colombier 	struct passwd *pw;
23*8ccd4a63SDavid du Colombier 
24*8ccd4a63SDavid du Colombier 	pw = getpwuid(getuid());
25*8ccd4a63SDavid du Colombier 	if(pw == nil)
26*8ccd4a63SDavid du Colombier 		return "none";
27*8ccd4a63SDavid du Colombier 	strecpy(user, user+sizeof user, pw->pw_name);
28*8ccd4a63SDavid du Colombier 	return user;
29*8ccd4a63SDavid du Colombier }
30*8ccd4a63SDavid du Colombier /*
31*8ccd4a63SDavid du Colombier  * Absent other hints, it works reasonably well to use
32*8ccd4a63SDavid du Colombier  * the X11 display name as the name space identifier.
33*8ccd4a63SDavid du Colombier  * This is how sam's B has worked since the early days.
34*8ccd4a63SDavid du Colombier  * Since most programs using name spaces are also using X,
35*8ccd4a63SDavid du Colombier  * this still seems reasonable.  Terminal-only sessions
36*8ccd4a63SDavid du Colombier  * can set $NAMESPACE.
37*8ccd4a63SDavid du Colombier  */
38*8ccd4a63SDavid du Colombier static char*
nsfromdisplay(void)39*8ccd4a63SDavid du Colombier nsfromdisplay(void)
40*8ccd4a63SDavid du Colombier {
41*8ccd4a63SDavid du Colombier 	char *disp, *p;
42*8ccd4a63SDavid du Colombier 
43*8ccd4a63SDavid du Colombier 	if((disp = getenv("DISPLAY")) == nil){
44*8ccd4a63SDavid du Colombier 		werrstr("$DISPLAY not set");
45*8ccd4a63SDavid du Colombier 		return nil;
46*8ccd4a63SDavid du Colombier 	}
47*8ccd4a63SDavid du Colombier 
48*8ccd4a63SDavid du Colombier 	/* canonicalize: xxx:0.0 => xxx:0 */
49*8ccd4a63SDavid du Colombier 	p = strrchr(disp, ':');
50*8ccd4a63SDavid du Colombier 	if(p){
51*8ccd4a63SDavid du Colombier 		p++;
52*8ccd4a63SDavid du Colombier 		while(isdigit((uchar)*p))
53*8ccd4a63SDavid du Colombier 			p++;
54*8ccd4a63SDavid du Colombier 		if(strcmp(p, ".0") == 0)
55*8ccd4a63SDavid du Colombier 			*p = 0;
56*8ccd4a63SDavid du Colombier 	}
57*8ccd4a63SDavid du Colombier 
58*8ccd4a63SDavid du Colombier 	return smprint("/tmp/ns.%s.%s", getuser(), disp);
59*8ccd4a63SDavid du Colombier }
60*8ccd4a63SDavid du Colombier 
61*8ccd4a63SDavid du Colombier char*
getns(void)62*8ccd4a63SDavid du Colombier getns(void)
63*8ccd4a63SDavid du Colombier {
64*8ccd4a63SDavid du Colombier 	char *ns;
65*8ccd4a63SDavid du Colombier 
66*8ccd4a63SDavid du Colombier 	ns = getenv("NAMESPACE");
67*8ccd4a63SDavid du Colombier 	if(ns == nil)
68*8ccd4a63SDavid du Colombier 		ns = nsfromdisplay();
69*8ccd4a63SDavid du Colombier 	if(ns == nil){
70*8ccd4a63SDavid du Colombier 		werrstr("$NAMESPACE not set, %r");
71*8ccd4a63SDavid du Colombier 		return nil;
72*8ccd4a63SDavid du Colombier 	}
73*8ccd4a63SDavid du Colombier 	return ns;
74*8ccd4a63SDavid du Colombier }
75*8ccd4a63SDavid du Colombier 
76*8ccd4a63SDavid du Colombier int
dialfactotum(void)77*8ccd4a63SDavid du Colombier dialfactotum(void)
78*8ccd4a63SDavid du Colombier {
79*8ccd4a63SDavid du Colombier 	int fd;
80*8ccd4a63SDavid du Colombier 	struct sockaddr_un su;
81*8ccd4a63SDavid du Colombier 	char *name;
82*8ccd4a63SDavid du Colombier 
83*8ccd4a63SDavid du Colombier 	name = smprint("%s/factotum", getns());
84*8ccd4a63SDavid du Colombier 
85*8ccd4a63SDavid du Colombier 	if(name == nil || access(name, 0) < 0)
86*8ccd4a63SDavid du Colombier 		return -1;
87*8ccd4a63SDavid du Colombier 	memset(&su, 0, sizeof su);
88*8ccd4a63SDavid du Colombier 	su.sun_family = AF_UNIX;
89*8ccd4a63SDavid du Colombier 	if(strlen(name)+1 > sizeof su.sun_path){
90*8ccd4a63SDavid du Colombier 		werrstr("socket name too long");
91*8ccd4a63SDavid du Colombier 		return -1;
92*8ccd4a63SDavid du Colombier 	}
93*8ccd4a63SDavid du Colombier 	strcpy(su.sun_path, name);
94*8ccd4a63SDavid du Colombier 	if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
95*8ccd4a63SDavid du Colombier 		werrstr("socket: %r");
96*8ccd4a63SDavid du Colombier 		return -1;
97*8ccd4a63SDavid du Colombier 	}
98*8ccd4a63SDavid du Colombier 	if(connect(fd, (struct sockaddr*)&su, sizeof su) < 0){
99*8ccd4a63SDavid du Colombier 		werrstr("connect %s: %r", name);
100*8ccd4a63SDavid du Colombier 		close(fd);
101*8ccd4a63SDavid du Colombier 		return -1;
102*8ccd4a63SDavid du Colombier 	}
103*8ccd4a63SDavid du Colombier 
104*8ccd4a63SDavid du Colombier 	return lfdfd(fd);
105*8ccd4a63SDavid du Colombier }
106*8ccd4a63SDavid du Colombier 
107