libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

commit 699b4f8cc0d0451e87c381140cd5685949e5347a
parent 3f4d1c6275cbdebcc038a87f12020f0c6326ffb5
Author: Kris Maglione <jg@suckless.org>
Date:   Sun,  3 Feb 2008 17:10:10 -0500

Add ixp_namespace, ixp_nsmount, ixp_smprint. Bump API version.

Diffstat:
include/ixp.h | 14+++++++++-----
libixp/client.c | 29++++++++++++++++++++++++-----
libixp/error.c | 4++--
libixp/intmap.c | 2+-
libixp/request.c | 10+++++-----
libixp/rpc.c | 6+++---
libixp/server.c | 2+-
libixp/socket.c | 8++++----
libixp/transport.c | 9+++++----
libixp/util.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
libixp_rubythread/thread_ruby.c | 16++++++++++++++--
mk/lib.mk | 2++
mk/many.mk | 1+
mk/one.mk | 1+
mk/so.mk | 2++
util/compile | 4+++-
16 files changed, 197 insertions(+), 39 deletions(-)

diff --git a/include/ixp.h b/include/ixp.h @@ -7,7 +7,7 @@ #include <sys/types.h> #include <sys/select.h> -#define IXP_API 87 +#define IXP_API 89 /* Gunk */ #if defined(IXP_NEEDAPI) && IXP_API < IXP_NEEDAPI @@ -498,7 +498,6 @@ int ixp_pthread_init(void); /* client.c */ int ixp_close(IxpCFid*); -Stat* ixp_fstat(IxpCFid*); long ixp_pread(IxpCFid*, void*, long, vlong); int ixp_print(IxpCFid*, const char*, ...); long ixp_pwrite(IxpCFid*, const void*, long, vlong); @@ -508,8 +507,10 @@ void ixp_unmount(IxpClient*); int ixp_vprint(IxpCFid*, const char*, va_list); long ixp_write(IxpCFid*, const void*, long); IxpCFid* ixp_create(IxpClient*, const char*, uint perm, uchar mode); -IxpClient* ixp_mount(char*); +IxpStat* ixp_fstat(IxpCFid*); +IxpClient* ixp_mount(const char*); IxpClient* ixp_mountfd(int); +IxpClient* ixp_nsmount(const char*); IxpCFid* ixp_open(IxpClient*, const char*, uchar); IxpStat* ixp_stat(IxpClient*, const char*); @@ -566,11 +567,14 @@ long ixp_settimer(IxpServer*, long, void (*)(long, void*), void*); int ixp_unsettimer(IxpServer*, long); /* util.c */ +void ixp_cleanname(char*); void* ixp_emalloc(uint); void* ixp_emallocz(uint); +void ixp_eprint(const char*, ...); void* ixp_erealloc(void*, uint); char* ixp_estrdup(const char*); -void ixp_eprint(const char*, ...); -uint ixp_tokenize(char**, uint len, char*, char); +char* ixp_namespace(void); +char* ixp_smprint(const char*, ...); uint ixp_strlcat(char*, const char*, uint); +uint ixp_tokenize(char**, uint len, char*, char); diff --git a/libixp/client.c b/libixp/client.c @@ -77,7 +77,7 @@ dofcall(IxpClient *c, Fcall *fcall) { werrstr("received mismatched fcall"); goto fail; } - memcpy(fcall, ret, sizeof(*fcall)); + memcpy(fcall, ret, sizeof *fcall); free(ret); return 1; fail: @@ -121,15 +121,19 @@ allocmsg(IxpClient *c, int n) { /** * Function: ixp_mountfd * Function: ixp_mount + * Function: ixp_nsmount * * Params: * fd - A file descriptor which is already connected * to a 9P server. * address - An address (in Plan 9 resource fomat) on * which to connect to a 9P server. + * name - The name of the socket in the process's canonical + * namespace directory. * - * Initiate a 9P connection with the server at - * P<address> or connected to on P<fd>. + * Initiate a 9P connection with the server at P<address>, + * connected to on P<fd>, or under the process's namespace + * directory as P<name>. * * Returns: * A pointer to a new 9P client. @@ -140,7 +144,7 @@ ixp_mountfd(int fd) { IxpClient *c; Fcall fcall; - c = emallocz(sizeof(*c)); + c = emallocz(sizeof *c); c->fd = fd; muxinit(c); @@ -187,7 +191,7 @@ ixp_mountfd(int fd) { } IxpClient* -ixp_mount(char *address) { +ixp_mount(const char *address) { int fd; fd = ixp_dial(address); @@ -196,6 +200,21 @@ ixp_mount(char *address) { return ixp_mountfd(fd); } +IxpClient* +ixp_nsmount(const char *name) { + char *address; + IxpClient *c; + + address = ixp_namespace(); + if(address) + address = ixp_smprint("unix!%s/%s", address, name); + if(address == nil) + return nil; + c = ixp_mount(address); + free(address); + return c; +} + static IxpCFid* walk(IxpClient *c, const char *path) { IxpCFid *f; diff --git a/libixp/error.c b/libixp/error.c @@ -78,7 +78,7 @@ void errstr(char *buf, int n) { char tmp[IXP_ERRMAX]; - strncpy(tmp, buf, sizeof(tmp)); + strncpy(tmp, buf, sizeof tmp); rerrstr(buf, n); strncpy(thread->errbuf(), tmp, IXP_ERRMAX); errno = EPLAN9; @@ -95,7 +95,7 @@ werrstr(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - ixp_vsnprint(tmp, sizeof(tmp), fmt, ap); + ixp_vsnprint(tmp, sizeof tmp, fmt, ap); va_end(ap); strncpy(thread->errbuf(), tmp, IXP_ERRMAX); errno = EPLAN9; diff --git a/libixp/intmap.c b/libixp/intmap.c @@ -100,7 +100,7 @@ insertkey(Intmap *map, ulong id, void *v) { ov = f->aux; f->aux = v; }else{ - f = emallocz(sizeof(*f)); + f = emallocz(sizeof *f); f->id = id; f->aux = v; h = hashid(map, id); diff --git a/libixp/request.c b/libixp/request.c @@ -73,7 +73,7 @@ static void* createfid(Intmap *map, int fid, Ixp9Conn *pc) { Fid *f; - f = emallocz(sizeof(Fid)); + f = emallocz(sizeof *f); pc->ref++; f->conn = pc; f->fid = fid; @@ -116,7 +116,7 @@ handlefcall(IxpConn *c) { goto Fail; thread->unlock(&pc->rlock); - req = emallocz(sizeof(Ixp9Req)); + req = emallocz(sizeof *req); pc->ref++; req->conn = pc; req->srv = pc->srv; @@ -425,7 +425,7 @@ voidrequest(void *t) { pc = r->conn; pc->ref++; - tr = emallocz(sizeof(Ixp9Req)); + tr = emallocz(sizeof *tr); tr->ifcall.type = TFlush; tr->ifcall.tag = IXP_NOTAG; tr->ifcall.oldtag = r->ifcall.tag; @@ -444,7 +444,7 @@ voidfid(void *t) { pc = f->conn; pc->ref++; - tr = emallocz(sizeof(Ixp9Req)); + tr = emallocz(sizeof *tr); tr->ifcall.type = TClunk; tr->ifcall.tag = IXP_NOTAG; tr->ifcall.fid = f->fid; @@ -476,7 +476,7 @@ serve_9pcon(IxpConn *c) { if(fd < 0) return; - pc = emallocz(sizeof(Ixp9Conn)); + pc = emallocz(sizeof *pc); pc->ref++; pc->srv = c->aux; pc->rmsg.size = 1024; diff --git a/libixp/rpc.c b/libixp/rpc.c @@ -88,7 +88,7 @@ muxrecv(IxpClient *mux) thread->lock(&mux->rlock); if(ixp_recvmsg(mux->fd, &mux->rmsg) == 0) goto fail; - f = emallocz(sizeof(Fcall)); + f = emallocz(sizeof *f); if(ixp_msg2fcall(&mux->rmsg, f) == 0) { free(f); f = nil; @@ -214,10 +214,10 @@ gettag(IxpClient *mux, IxpRpc *r) mw = 1; else mw <<= 1; - w = realloc(mux->wait, mw*sizeof(w[0])); + w = realloc(mux->wait, mw * sizeof *w); if(w == nil) return -1; - memset(w+mux->mwait, 0, (mw-mux->mwait)*sizeof(w[0])); + memset(w+mux->mwait, 0, (mw-mux->mwait) * sizeof *w); mux->wait = w; mux->freetag = mux->mwait; mux->mwait = mw; diff --git a/libixp/server.c b/libixp/server.c @@ -38,7 +38,7 @@ ixp_listen(IxpServer *s, int fd, void *aux, ) { IxpConn *c; - c = emallocz(sizeof(IxpConn)); + c = emallocz(sizeof *c); c->fd = fd; c->aux = aux; c->srv = s; diff --git a/libixp/socket.c b/libixp/socket.c @@ -52,10 +52,10 @@ static int sock_unix(char *address, sockaddr_un *sa, socklen_t *salen) { int fd; - memset(sa, 0, sizeof(*sa)); + memset(sa, 0, sizeof *sa); sa->sun_family = AF_UNIX; - strncpy(sa->sun_path, address, sizeof(sa->sun_path)); + strncpy(sa->sun_path, address, sizeof sa->sun_path); *salen = SUN_LEN(sa); fd = socket(AF_UNIX, SOCK_STREAM, 0); @@ -94,7 +94,7 @@ announce_unix(char *file) { if(fd == -1) return fd; - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0) + if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof yes) < 0) goto fail; unlink(file); @@ -123,7 +123,7 @@ alookup(char *host, int announce) { if(port == nil) return nil; - memset(&hints, 0, sizeof(hints)); + memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; diff --git a/libixp/transport.c b/libixp/transport.c @@ -24,7 +24,7 @@ mread(int fd, IxpMsg *msg, uint count) { if(n > count) n = count; - r = ixp_thread->read(fd, msg->pos, n); + r = thread->read(fd, msg->pos, n); if(r > 0) msg->pos += r; return r; @@ -41,7 +41,7 @@ readn(int fd, IxpMsg *msg, uint count) { if(r == -1 && errno == EINTR) continue; if(r == 0) { - werrstr("broken pipe"); + werrstr("broken pipe: %r"); return count - num; } num -= r; @@ -55,11 +55,11 @@ ixp_sendmsg(int fd, IxpMsg *msg) { msg->pos = msg->data; while(msg->pos < msg->end) { - r = ixp_thread->write(fd, msg->pos, msg->end - msg->pos); + r = thread->write(fd, msg->pos, msg->end - msg->pos); if(r < 1) { if(errno == EINTR) continue; - werrstr("broken pipe"); + werrstr("broken pipe: %r"); return 0; } msg->pos += r; @@ -94,3 +94,4 @@ ixp_recvmsg(int fd, IxpMsg *msg) { msg->end = msg->pos; return msize; } + diff --git a/libixp/util.c b/libixp/util.c @@ -6,8 +6,122 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <pwd.h> #include "ixp_local.h" +char* +ixp_smprint(const char *fmt, ...) { + va_list ap; + char *s; + + va_start(ap, fmt); + s = ixp_vsmprint(fmt, ap); + va_end(ap); + if(s == nil) + ixp_werrstr("no memory"); + return s; +} + +static char* +_user(void) { + static char *user; + struct passwd *pw; + + if(user == nil) { + pw = getpwuid(getuid()); + if(pw) + user = strdup(pw->pw_name); + } + if(user == nil) + user = "none"; + return user; +} + +static int +rmkdir(char *path, int mode) { + char *p; + int ret; + char c; + + for(p = path+1; ; p++) { + c = *p; + if((c == '/') || (c == '\0')) { + *p = '\0'; + ret = mkdir(path, mode); + if((ret == -1) && (errno != EEXIST)) { + ixp_werrstr("Can't create path '%s': %r", path); + return 0; + } + *p = c; + } + if(c == '\0') + break; + } + return 1; +} + +static char* +ns_display(void) { + char *path, *disp; + struct stat st; + + disp = getenv("DISPLAY"); + if(disp == nil || disp[0] == '\0') { + ixp_werrstr("$DISPLAY is unset"); + return nil; + } + + disp = estrdup(disp); + path = &disp[strlen(disp) - 2]; + if(path > disp && !strcmp(path, ".0")) + *path = '\0'; + + path = ixp_smprint("/tmp/ns.%s.%s", _user(), disp); + free(disp); + + if(!rmkdir(path, 0700)) + ; + else if(stat(path, &st)) + ixp_werrstr("Can't stat ns_path '%s': %r", path); + else if(getuid() != st.st_uid) + ixp_werrstr("ns_path '%s' exists but is not owned by you", path); + else if((st.st_mode & 077) && chmod(path, st.st_mode & ~077)) + ixp_werrstr("Namespace path '%s' exists, but has wrong permissions: %r", path); + else + return path; + free(path); + return nil; +} + +/** + * Function: ixp_namespace + * + * Returns the path of the canonical 9p namespace directory. + * Either the value of $NAMESPACE, if it's set, or, roughly, + * /tmp/ns.${USER}.${DISPLAY:%.0=%}. In the latter case, the + * directory is created if it doesn't exist, and it is + * ensured to be owned by the current user, with no group or + * other permissions. + * + * Returns: + * A statically allocated string which must not be freed + * or altered by the caller. The same value is returned + * upon successive calls. + */ +/* Not especially threadsafe. */ +char* +ixp_namespace(void) { + static char *namespace; + + if(namespace == nil) + namespace = getenv("NAMESPACE"); + if(namespace == nil) + namespace = ns_display(); + return namespace; +} + void eprint(const char *fmt, ...) { va_list ap; @@ -38,7 +152,7 @@ mfatal(char *name, uint size) { char sizestr[8]; int i; - i = sizeof(sizestr); + i = sizeof sizestr; do { sizestr[--i] = '0' + (size%10); size /= 10; @@ -115,12 +229,12 @@ strlcat(char *dst, const char *src, uint size) { d++; len = n; - while(*s != '\0') { - if(n-- > 0) - *d++ = *s; - s++; - } + while(*s != '\0' && n-- > 0) + *d++ = *s++; + while(*s++ != '\0') + n--; if(len > 0) *d = '\0'; return size - n - 1; } + diff --git a/libixp_rubythread/thread_ruby.c b/libixp_rubythread/thread_ruby.c @@ -145,14 +145,26 @@ rwakeall(IxpRendez *r) { /* Yielding IO */ static ssize_t _read(int fd, void *buf, size_t size) { + int n; + rb_thread_wait_fd(fd); - return read(fd, buf, size); + n = read(fd, buf, size); + + if(n < 0 && errno == EINTR) + rb_thread_schedule(); + return n; } static ssize_t _write(int fd, const void *buf, size_t size) { + int n; + rb_thread_fd_writable(fd); - return write(fd, buf, size); + n = write(fd, buf, size); + + if(n < 0 && errno == EINTR) + rb_thread_schedule(); + return n; } static IxpThread ixp_rthread = { diff --git a/mk/lib.mk b/mk/lib.mk @@ -11,6 +11,8 @@ depend: ${OBJ:=.depend} libclean: for i in $(LIB) $(OFILES); do \ + [ -e $$i ] && \ + echo CLEAN $$($(CLEANNAME) $(BASE)$$i); \ rm -f $$i; \ done 2>/dev/null || true diff --git a/mk/many.mk b/mk/many.mk @@ -13,6 +13,7 @@ printinstall: manyclean: for i in ${TARG:=.o} ${TARG:=.O} $(OFILES); do \ + [ -e $$i ] && \ echo CLEAN $$($(CLEANNAME) $(BASE)$$i); \ rm -f $$i; \ done 2>/dev/null || true diff --git a/mk/one.mk b/mk/one.mk @@ -14,6 +14,7 @@ printinstall: oneclean: for i in $(PROG) $(OFILES); do \ + [ -e $$i ] && \ echo CLEAN $$($(CLEANNAME) $(BASE)$$i); \ rm -f $$i; \ done 2>/dev/null || true diff --git a/mk/so.mk b/mk/so.mk @@ -12,6 +12,8 @@ depend: ${OBJ:=.depend} soclean: for i in $(SO) $(OFILES_PIC); do \ + [ -e $$i ] && \ + echo CLEAN $$($(CLEANNAME) $(BASE)$$i); \ rm -f $$i; \ done 2>/dev/null || true diff --git a/util/compile b/util/compile @@ -9,7 +9,7 @@ xtmp=/tmp/cc.$$.$USER.out echo CC $($bin/cleanname ${BASE}$outfile) [ -n "$noisycc" ] && echo $CC -o $outfile $CFLAGS $@ -$CC -o $outfile $CFLAGS $@ 2>$xtmp +$CC -o $outfile $CFLAGS $@ >$xtmp 2>&1 status=$? base=$(echo $BASE | sed 's/,/\\,/g') @@ -57,6 +57,8 @@ undup() { # GCC is crap. cat $xtmp | sed "s,^$re,$base&,g; s,\([[:space:]]\)$re,\1$base\2,g" | egrep -v ': error: .Each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: In function |: At top level:|support .long long.|use of C99 long long|ISO C forbids conversion' | sed 's/ .first use in this function.$//; s/\"\([^\"][^\"]*\)\", line \([0-9][0-9]*\)/\1:\2/g' | + awk '$1 == "warning:"{t=$2" "$1; sub(/^[^ ]+ [^ ]+ /, ""); $0 = t" "$0}; //' | + awk '{sub(/\[/, ": [", $1); print}' | undup 1>&2 rm -f $xtmp