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