aboutsummaryrefslogtreecommitdiff
path: root/src/lib9
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib9')
-rw-r--r--src/lib9/_p9translate.c46
-rw-r--r--src/lib9/access.c19
-rw-r--r--src/lib9/getns.c74
-rw-r--r--src/lib9/malloc.c11
-rw-r--r--src/lib9/open.c38
-rw-r--r--src/lib9/pipe.c10
-rw-r--r--src/lib9/post9p.c40
-rw-r--r--src/lib9/sendfd.c79
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;
+}