diff options
Diffstat (limited to 'src/lib9')
-rw-r--r-- | src/lib9/_p9translate.c | 46 | ||||
-rw-r--r-- | src/lib9/access.c | 19 | ||||
-rw-r--r-- | src/lib9/getns.c | 74 | ||||
-rw-r--r-- | src/lib9/malloc.c | 11 | ||||
-rw-r--r-- | src/lib9/open.c | 38 | ||||
-rw-r--r-- | src/lib9/pipe.c | 10 | ||||
-rw-r--r-- | src/lib9/post9p.c | 40 | ||||
-rw-r--r-- | src/lib9/sendfd.c | 79 |
8 files changed, 317 insertions, 0 deletions
diff --git a/src/lib9/_p9translate.c b/src/lib9/_p9translate.c new file mode 100644 index 00000000..4eb6eac9 --- /dev/null +++ b/src/lib9/_p9translate.c @@ -0,0 +1,46 @@ +#include <u.h> +#include <libc.h> + +/* + * I don't want too many of these, + * but the ones we have are just too useful. + */ +static struct { + char *old; + char *new; +} replace[] = { + "#9", nil, /* must be first */ + "#d", "/dev/fd", +}; + +char* +_p9translate(char *old) +{ + char *new; + int i, olen, nlen, len; + + if(replace[0].new == nil){ + replace[0].new = getenv("PLAN9"); + if(replace[0].new == nil) + replace[0].new = "/usr/local/plan9"; + } + + for(i=0; i<nelem(replace); i++){ + if(!replace[i].new) + continue; + olen = strlen(replace[i].old); + if(strncmp(old, replace[i].old, olen) != 0 + || (old[olen] != '\0' && old[olen] != '/')) + continue; + nlen = strlen(replace[i].new); + len = strlen(old)+nlen-olen; + new = malloc(len+1); + if(new == nil) + return nil; + strcpy(new, replace[i].new); + strcpy(new+nlen, old+olen); + assert(strlen(new) == len); + return new; + } + return old; +} diff --git a/src/lib9/access.c b/src/lib9/access.c new file mode 100644 index 00000000..20b00c32 --- /dev/null +++ b/src/lib9/access.c @@ -0,0 +1,19 @@ +#include <u.h> +#define NOPLAN9DEFINES +#include <libc.h> + +char *_p9translate(char*); + +int +p9access(char *xname, int what) +{ + int ret; + char *name; + + if((name = _p9translate(xname)) == nil) + return -1; + ret = access(name, what); + if(name != xname) + free(name); + return ret; +} diff --git a/src/lib9/getns.c b/src/lib9/getns.c new file mode 100644 index 00000000..29bc857c --- /dev/null +++ b/src/lib9/getns.c @@ -0,0 +1,74 @@ +#include <u.h> +#include <libc.h> +#include <ctype.h> + +/* + * 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) +{ + int fd; + Dir *d; + 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; + } + + p = smprint("/tmp/ns.%s.%s", getuser(), disp); + free(disp); + if(p == nil){ + werrstr("out of memory"); + return p; + } + if((fd=create(p, OREAD, DMDIR|0700)) >= 0){ + close(fd); + return p; + } + if((d = dirstat(p)) == nil){ + free(d); + werrstr("stat %s: %r", p); + free(p); + return nil; + } + if((d->mode&0777) != 0700 || strcmp(d->uid, getuser()) != 0){ + werrstr("bad name space dir %s", p); + free(p); + free(d); + return nil; + } + free(d); + return p; +} + +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; +} diff --git a/src/lib9/malloc.c b/src/lib9/malloc.c new file mode 100644 index 00000000..b75d2f07 --- /dev/null +++ b/src/lib9/malloc.c @@ -0,0 +1,11 @@ +#include <u.h> +#define NOPLAN9DEFINES +#include <libc.h> + +void* +p9malloc(ulong n) +{ + if(n == 0) + n++; + return malloc(n); +} diff --git a/src/lib9/open.c b/src/lib9/open.c new file mode 100644 index 00000000..bb597e8f --- /dev/null +++ b/src/lib9/open.c @@ -0,0 +1,38 @@ +#include <u.h> +#define NOPLAN9DEFINES +#include <libc.h> + +extern char* _p9translate(char*); + +int +p9open(char *xname, int mode) +{ + char *name; + int cexec, rclose; + int fd, umode; + + umode = mode&3; + cexec = mode&OCEXEC; + rclose = mode&ORCLOSE; + mode &= ~(3|OCEXEC|ORCLOSE); + if(mode&OTRUNC){ + umode |= O_TRUNC; + mode ^= OTRUNC; + } + if(mode){ + werrstr("mode not supported"); + return -1; + } + if((name = _p9translate(xname)) == nil) + return -1; + fd = open(name, umode); + if(fd >= 0){ + if(cexec) + fcntl(fd, F_SETFL, FD_CLOEXEC); + if(rclose) + remove(name); + } + if(name != xname) + free(name); + return fd; +} diff --git a/src/lib9/pipe.c b/src/lib9/pipe.c new file mode 100644 index 00000000..f9fe2420 --- /dev/null +++ b/src/lib9/pipe.c @@ -0,0 +1,10 @@ +#include <u.h> +#define NOPLAN9DEFINES +#include <libc.h> +#include <sys/socket.h> + +int +p9pipe(int fd[2]) +{ + return socketpair(AF_UNIX, SOCK_STREAM, 0, fd); +} diff --git a/src/lib9/post9p.c b/src/lib9/post9p.c new file mode 100644 index 00000000..35ba3167 --- /dev/null +++ b/src/lib9/post9p.c @@ -0,0 +1,40 @@ +#include <u.h> +#include <libc.h> + +int +post9pservice(int fd, char *name) +{ + int i; + char *ns, *s; + Waitmsg *w; + + if((ns = getns()) == nil) + return -1; + s = smprint("unix!%s/%s", ns, name); + free(ns); + if(s == nil) + return -1; + switch(rfork(RFPROC|RFFDG)){ + case -1: + return -1; + case 0: + dup(fd, 0); + dup(fd, 1); + for(i=3; i<20; i++) + close(i); + execlp("9pserve", "9pserve", "-u", s, (char*)0); + fprint(2, "exec 9pserve: %r\n"); + _exits("exec"); + default: + w = wait(); + close(fd); + free(s); + if(w->msg && w->msg[0]){ + free(w); + werrstr("9pserve failed"); + return -1; + } + free(w); + return 0; + } +} diff --git a/src/lib9/sendfd.c b/src/lib9/sendfd.c new file mode 100644 index 00000000..b3a2448f --- /dev/null +++ b/src/lib9/sendfd.c @@ -0,0 +1,79 @@ +#include <u.h> +#define NOPLAN9DEFINES +#include <libc.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <unistd.h> +#include <errno.h> + +typedef struct Sendfd Sendfd; +struct Sendfd { + struct cmsghdr cmsg; + int fd; +}; + +int +sendfd(int s, int fd) +{ + char buf[1]; + struct iovec iov; + struct msghdr msg; + int n; + Sendfd sfd; + + buf[0] = 0; + iov.iov_base = buf; + iov.iov_len = 1; + + memset(&msg, 0, sizeof msg); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + sfd.cmsg.cmsg_len = sizeof sfd; + sfd.cmsg.cmsg_level = SOL_SOCKET; + sfd.cmsg.cmsg_type = SCM_RIGHTS; + sfd.fd = fd; + + msg.msg_control = &sfd; + msg.msg_controllen = sizeof sfd; + + if((n=sendmsg(s, &msg, 0)) != iov.iov_len) + return -1; + return 0; +} + +int +recvfd(int s) +{ + int n; + char buf[1]; + struct iovec iov; + struct msghdr msg; + Sendfd sfd; + + iov.iov_base = buf; + iov.iov_len = 1; + + memset(&msg, 0, sizeof msg); + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + memset(&sfd, 0, sizeof sfd); + sfd.fd = -1; + sfd.cmsg.cmsg_len = sizeof sfd; + sfd.cmsg.cmsg_level = SOL_SOCKET; + sfd.cmsg.cmsg_type = SCM_RIGHTS; + + msg.msg_control = &sfd; + msg.msg_controllen = sizeof sfd; + + if((n=recvmsg(s, &msg, 0)) < 0) + return -1; + if(n==0 && sfd.fd==-1){ + werrstr("eof in recvfd"); + return -1; + } + return sfd.fd; +} |