ref: cce4ca5a6c55eb6fff53f9b7092e2518185a984c
dir: /posix-factotum.c/
#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; }