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