libixp

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

commit 2e20a5ac9f7945a79961df7807f2dbc12fef7f99
parent 0b3d92b799ddfac0f39c30ce208ae70025e3ea4a
Author: Kris Maglione <jg@suckless.org>
Date:   Wed, 28 Nov 2007 18:19:53 -0500

Apparantly, there is a lot of uncommitted cleanup. I've added a
simple file server by Ron Minnich to the examples dir.

Diffstat:
cmd/Makefile | 5+++--
cmd/ixpc.c | 29++++++-----------------------
config.mk | 4++--
examples/Makefile | 10++++++++++
examples/ixpsrv.c | 539+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
include/Makefile | 1+
include/ixp.h | 337++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
include/ixp_local.h | 35+++++++++++++++++++++++++----------
libixp/Makefile | 6------
libixp/client.c | 12++++++------
libixp/convert.c | 30++++++++++++++++--------------
libixp/error.c | 10+++++-----
libixp/fcall.h | 54------------------------------------------------------
libixp/fcall.h.nounion | 53-----------------------------------------------------
libixp/ixp_fcall.h | 53-----------------------------------------------------
libixp/message.c | 2+-
libixp/request.c | 4++--
libixp/socket.c | 6+++---
libixp/transport.c | 2+-
man/Makefile | 1+
mk/gcc.mk | 1-
mk/hdr.mk | 4++--
mk/ixp.mk | 3+++
test/client.c | 154++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
test/mkfile | 4++--
test/o.client | 0
util/compile | 1+
util/link | 1+
28 files changed, 932 insertions(+), 429 deletions(-)

diff --git a/cmd/Makefile b/cmd/Makefile @@ -2,8 +2,9 @@ ROOT=.. include ${ROOT}/mk/hdr.mk include ${ROOT}/mk/ixp.mk +LDFLAGS += -L${ROOT}/lib -lixp TARG = ixpc -OBJ = ixpc LIB = ${ROOT}/lib/libixp.a -include ${ROOT}/mk/one.mk +include ${ROOT}/mk/many.mk + diff --git a/cmd/ixpc.c b/cmd/ixpc.c @@ -8,28 +8,11 @@ #include <string.h> #include <time.h> #include <unistd.h> -#include "ixp.h" +#include <ixp_local.h> /* Temporary */ #define fatal(...) ixp_eprint("ixpc: fatal: " __VA_ARGS__); \ -char *argv0; -#define ARGBEGIN int _argi, _argtmp, _inargv=0; char *_argv; \ - if(!argv0)argv0=ARGF(); _inargv=1; \ - while(argc && argv[0][0] == '-') { \ - _argi=1; _argv=*argv++; argc--; \ - while(_argv[_argi]) switch(_argv[_argi++]) -#define ARGEND }_inargv=0;USED(_argtmp);USED(_argv);USED(_argi) -#define ARGF() ((_inargv && _argv[_argi]) ? \ - (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \ - : ((argc > 0) ? (argc--, *argv++) : ((char*)0))) -#define EARGF(f) ((_inargv && _argv[_argi]) ? \ - (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \ - : ((argc > 0) ? (argc--, *argv++) : ((f), (char*)0))) -#define USED(x) if(x){}else -#define SET(x) ((x)=0) -#define nil ((void*)0) - static IxpClient *client; static void @@ -47,7 +30,7 @@ write_data(IxpCFid *fid, char *name) { void *buf; uint len; - buf = ixp_emalloc(fid->iounit);; + buf = emalloc(fid->iounit);; do { len = read(0, buf, fid->iounit); if(len >= 0 && ixp_write(fid, buf, len) != len) @@ -151,7 +134,7 @@ xawrite(int argc, char *argv[]) { nbuf = 0; mbuf = 128; - buf = ixp_emalloc(mbuf); + buf = emalloc(mbuf); while(argc) { arg = ARGF(); len = strlen(arg); @@ -222,7 +205,7 @@ xread(int argc, char *argv[]) { if(fid == nil) fatal("Can't open file '%s': %s\n", file, ixp_errbuf()); - buf = ixp_emalloc(fid->iounit); + buf = emalloc(fid->iounit); while((count = ixp_read(fid, buf, fid->iounit)) > 0) write(1, buf, count); @@ -272,8 +255,8 @@ xls(int argc, char *argv[]) { nstat = 0; mstat = 16; - stat = ixp_emalloc(sizeof(*stat) * mstat); - buf = ixp_emalloc(fid->iounit); + stat = emalloc(sizeof(*stat) * mstat); + buf = emalloc(fid->iounit); while((count = ixp_read(fid, buf, fid->iounit)) > 0) { m = ixp_message(buf, count, MsgUnpack); while(m.pos < m.end) { diff --git a/config.mk b/config.mk @@ -21,10 +21,11 @@ INCLUDE = ${PREFIX}/include # Includes and libs INCPATH = .:${ROOT}/include:${INCLUDE}:/usr/include LIBS = -L/usr/lib -lc +MKDEP = cpp -M # Flags include ${ROOT}/mk/gcc.mk -CFLAGS = -g -Wall ${INCS} -DVERSION=\"${VERSION}\" +CFLAGS = -g ${INCS} -DIXPlint -DVERSION=\"${VERSION}\" LDFLAGS = -g ${LIBS} # Compiler @@ -40,5 +41,4 @@ AR = ar crs #LDFLAGS = ${LIBS} -R${PREFIX}/lib #LDFLAGS += -lsocket -lnsl #CFLAGS += -xtarget=ultra -FCALL_H_VERSION=.nounion diff --git a/examples/Makefile b/examples/Makefile @@ -0,0 +1,10 @@ +ROOT=.. +include ${ROOT}/mk/hdr.mk +include ${ROOT}/mk/ixp.mk + +LDFLAGS += -L${ROOT}/lib -lixp +TARG = ixpsrv +LIB = ${ROOT}/lib/libixp.a + +include ${ROOT}/mk/many.mk + diff --git a/examples/ixpsrv.c b/examples/ixpsrv.c @@ -0,0 +1,539 @@ +/* Copyright ©2007 Ron Minnich <rminnich at gmail dot com> +/* Copyright ©2007 Kris Maglione <maglione.k@gmail.com> + * See LICENSE file for license details. + */ + +/* This is a simple 9P file server which serves a normal filesystem + * hierarchy. While some of the code is from wmii, the server is by + * Ron. + * + * Note: I added an ifdef for Linux vs. BSD for the mount call, so + * this compiles on BSD, but it won't actually run. It should, + * ideally, have the option of not mounting the FS. + * --Kris + */ +#include <assert.h> +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/param.h> +#include <sys/mount.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <time.h> +#include <unistd.h> + +#include <ixp_local.h> + +/* Temporary */ +#define fatal(...) ixp_eprint("ixpsrv: fatal: " __VA_ARGS__) +#define debug(...) if(debuglevel) fprintf(stderr, "ixpsrv: " __VA_ARGS__) + +/* Datatypes: */ +typedef struct FidAux FidAux; +struct FidAux { + DIR *dir; + int fd; + char name[]; /* c99 */ +}; + +/* Error messages */ +static char + Enoperm[] = "permission denied", + Enofile[] = "file not found", + Ebadvalue[] = "bad value"; +/* Macros */ +#define QID(t, i) ((vlong)(t)) + +/* Global Vars */ +static IxpServer server; +static char *user; +static int debuglevel = 0; + +static void fs_open(Ixp9Req *r); +static void fs_walk(Ixp9Req *r); +static void fs_read(Ixp9Req *r); +static void fs_stat(Ixp9Req *r); +static void fs_write(Ixp9Req *r); +static void fs_clunk(Ixp9Req *r); +static void fs_flush(Ixp9Req *r); +static void fs_attach(Ixp9Req *r); +static void fs_create(Ixp9Req *r); +static void fs_remove(Ixp9Req *r); +static void fs_freefid(IxpFid *f); + +Ixp9Srv p9srv = { + .open= fs_open, + .walk= fs_walk, + .read= fs_read, + .stat= fs_stat, + .write= fs_write, + .clunk= fs_clunk, + .flush= fs_flush, + .attach=fs_attach, + .create=fs_create, + .remove=fs_remove, + .freefid=fs_freefid +}; + +static void +usage() { + fprintf(stderr, + "usage: %1$s [-a <address>] {create | read | ls [-ld] | remove | write} <file>\n" + " %1$s [-a <address>] xwrite <file> <data>\n" + " %1$s -v\n", argv0); + exit(1); +} + + +/* Utility Functions */ + +static FidAux* +newfidaux(char *name) { + FidAux *f; + + f = ixp_emallocz(sizeof(*f) + strlen(name) + 1); + f->fd = -1; + strcpy(f->name, name); + return f; +} +/* is this a dir? */ +/* -1 means it ain't anything .. */ +static int +isdir(char *path) { + struct stat buf; + + if (stat(path, &buf) < 0) + return -1; + + return S_ISDIR(buf.st_mode); +} + +/* This should be moved to libixp */ +static void +write_buf(Ixp9Req *r, char *buf, uint len) { + + if(r->ifcall.offset >= len) + return; + + len -= r->ifcall.offset; + if(len > r->ifcall.count) + len = r->ifcall.count; + r->ofcall.data = ixp_emalloc(len); + memcpy(r->ofcall.data, buf + r->ifcall.offset, len); + r->ofcall.count = len; +} + + +/* This should be moved to libixp */ +static void +write_to_buf(Ixp9Req *r, void *buf, uint *len, uint max) { + uint offset, count; + +// offset = (r->fid->omode&OAPPEND) ? *len : r->ifcall.offset; + offset = r->ifcall.offset; + if(offset > *len || r->ifcall.count == 0) { + r->ofcall.count = 0; + return; + } + + count = r->ifcall.count; + if(max && (count > max - offset)) + count = max - offset; + + *len = offset + count; + + if(max == 0) { + *(void **)buf = ixp_erealloc(*(void **)buf, *len + 1); + buf = *(void **)buf; + } + + memcpy((uchar*)buf + offset, r->ifcall.data, count); + r->ofcall.count = count; + ((char *)buf)[offset+count] = '\0'; +} + +static void +dostat(Stat *s, char *name, struct stat *buf) { + + s->type = 0; + s->dev = 0; + s->qid.type = buf->st_mode&S_IFMT; + s->qid.path = buf->st_ino; + s->qid.version = 0; + s->mode = buf->st_mode & 0777; + if (S_ISDIR(buf->st_mode)) { + s->mode |= P9_DMDIR; + s->qid.type |= QTDIR; + } + s->atime = buf->st_atime; + s->mtime = buf->st_mtime; + s->length = buf->st_size; + s->name =name; + s->uid = user; + s->gid = user; + s->muid = user; +} + +/* the gnu/linux guys have made a real mess of errno ... don't ask --ron */ +/* I agree. --Kris */ +void +rerrno(Ixp9Req *r, char *m) { +/* + char errbuf[128]; + respond(r, strerror_r(errno, errbuf, sizeof(errbuf))); + */ + respond(r, m); +} + +void +fs_attach(Ixp9Req *r) { + + debug("fs_attach(%p)\n", r); + + r->fid->qid.type = QTDIR; + r->fid->qid.path = (uintptr_t)r->fid; + r->fid->aux = newfidaux("/"); + r->ofcall.qid = r->fid->qid; + respond(r, nil); +} + +void +fs_walk(Ixp9Req *r) { + struct stat buf; + char *name; + FidAux *f; + int i; + + debug("fs_walk(%p)\n", r); + + f = r->fid->aux; + name = malloc(PATH_MAX); + strcpy(name, f->name); + if (stat(name, &buf) < 0){ + respond(r, Enofile); + return; + } + + /* build full path. Stat full path. Done */ + for(i=0; i < r->ifcall.nwname; i++) { + strcat(name, "/"); + strcat(name, r->ifcall.wname[i]); + if (stat(name, &buf) < 0){ + respond(r, Enofile); + free(name); + return; + } + r->ofcall.wqid[i].type = buf.st_mode&S_IFMT; + r->ofcall.wqid[i].path = buf.st_ino; + } + + r->newfid->aux = newfidaux(name); + r->ofcall.nwqid = i; + free(name); + respond(r, nil); +} + +void +fs_stat(Ixp9Req *r) { + struct stat st; + Stat s; + IxpMsg m; + char *name; + uchar *buf; + FidAux *f; + int size; + + debug("fs_stat(%p)\n", r); + debug("fs_stat %s\n", f->name); + + f = r->fid->aux; + + name = f->name; + if (stat(name, &st) < 0){ + respond(r, Enofile); + return; + } + + dostat(&s, name, &st); + r->fid->qid = s.qid; + r->ofcall.nstat = size = ixp_sizeof_stat(&s); + + buf = ixp_emallocz(size); + + m = ixp_message(buf, size, MsgPack); + ixp_pstat(&m, &s); + + r->ofcall.stat = m.data; + respond(r, nil); +} + +void +fs_read(Ixp9Req *r) { + FidAux *f; + char *buf; + int n, offset; + int size; + + debug("fs_read(%p)\n", r); + + f = r->fid->aux; + + if (f->dir) { + Stat s; + IxpMsg m; + + offset = 0; + size = r->ifcall.count; + buf = ixp_emallocz(size); + m = ixp_message((uchar*)buf, size, MsgPack); + + /* note: we don't really handle lots of things well, so do one thing + * at a time + */ + /*for(f=f->next; f; f=f->next) */{ + struct dirent *d; + struct stat st; + d = readdir(f->dir); + if (d) { + stat(d->d_name, &st); + dostat(&s, d->d_name, &st); + n = ixp_sizeof_stat(&s); + ixp_pstat(&m, &s); + offset += n; + } else n = 0; + } + r->ofcall.count = n; + r->ofcall.data = (char*)m.data; + respond(r, nil); + return; + } else { + r->ofcall.data = ixp_emallocz(r->ifcall.count); + if (! r->ofcall.data) { + respond(r, nil); + return; + } + r->ofcall.count = pread(f->fd, r->ofcall.data, r->ifcall.count, r->ifcall.offset); + if (r->ofcall.count < 0) + rerrno(r, Enoperm); + else + respond(r, nil); + return; + } + + /* + * This is an assert because this should this should not be called if + * the file is not open for reading. + */ + assert(!"Read called on an unreadable file"); +} + +void +fs_write(Ixp9Req *r) { + FidAux *f; + + debug("fs_write(%p)\n", r); + + if(r->ifcall.count == 0) { + respond(r, nil); + return; + } + f = r->fid->aux; + /* + * This is an assert because this function should not be called if + * the file is not open for writing. + */ + assert(!"Write called on an unwritable file"); +} + +void +fs_open(Ixp9Req *r) { + int dir; + FidAux *f; + + debug("fs_open(%p)\n", r); + + f = r->fid->aux; + dir = isdir(f->name); + /* fucking stupid linux -- open dir is a DIR */ + + if (dir) { + f->dir = opendir(f->name); + if (! f->dir){ + rerrno(r, Enoperm); + return; + } + } else { + f->fd = open(f->name, O_RDONLY); + if (f->fd < 0){ + rerrno(r, Enoperm); + return; + } + } + respond(r, nil); +} + + +void +fs_create(Ixp9Req *r) { + debug("fs_create(%p)\n", r); + respond(r, Enoperm); +} + +void +fs_remove(Ixp9Req *r) { + debug("fs_remove(%p)\n", r); + respond(r, Enoperm); + +} + +void +fs_clunk(Ixp9Req *r) { + int dir; + FidAux *f; + + debug("fs_clunk(%p)\n", f); + + f = r->fid->aux; + dir = isdir(f->name); + if (dir) { + (void) closedir(f->dir); + f->dir = NULL; + } else { + (void) close(f->fd); + f->fd = -1; + } + + respond(r, nil); +} + +void +fs_flush(Ixp9Req *r) { + debug("fs_flush(%p)\n", r); + respond(r, nil); +} + +void +fs_freefid(Fid *f) { + debug("fs_freefid(%p)\n", f); + free(f->aux); +} + +// mount -t 9p 127.1 /tmp/cache -o port=20006,noextend +/* Yuck. */ +#if defined(__linux__) +# define MF(n) MS_##n +# define mymount(src, dest, flags, opts) mount(src, dest, "9p", flags, opts) +#elif defined(__FreeBSD__) || defined(__OpenBSD__) +# define MF(n) MNT_##n +# define mymount(src, dest, flags, opts) mount("9p", dest, flags, src) +#endif + +static ulong mountflags = + MF(NOATIME) + | MF(NODEV) + /* | MF(NODIRATIME) */ + | MF(NOEXEC) + | MF(NOSUID) + | MF(RDONLY); + +int +getaddr(char *mountaddr, char **ip, char **port) { + char *cp; + + if (!mountaddr) + mountaddr = getenv("XCPU_PARENT"); + if (!mountaddr) + return -1; + + cp = mountaddr; + if (strcmp(cp, "tcp!")) + cp += 4; + + *ip = cp; + + cp = strstr(cp, "!"); + if (cp) + *port = cp + 1; + return strtoul(*port, 0, 0); +} + +int +main(int argc, char *argv[]) { + int fd; + int ret; + int domount, mountonly; + char *mountaddr; + char *address; + char *msg; + IxpConn *acceptor; + + domount = 0; + mountonly = 0; + address = getenv("IXP_ADDRESS"); + mountaddr = nil; + + ARGBEGIN{ + case 'v': + printf("%s-" VERSION ", ©2007 Ron Minnich\n", argv0); + exit(0); + case 'a': + address = EARGF(usage()); + break; + case 'd': + debuglevel++; + break; + case 'm': + domount++; + break; + case 'M': + mountonly++; + break; + default: + usage(); + }ARGEND; + + if(!address) + fatal("$IXP_ADDRESS not set\n"); + + fd = ixp_announce(address); + if(fd < 0) + fatal("%s\n", errstr); + + /* set up a fake client so we can grap connects. */ + acceptor = ixp_listen(&server, fd, &p9srv, serve_9pcon, NULL); + + /* we might need to mount ourselves. The bit of complexity is the need to fork so + * we can serve ourselves. We've done the listen so that's ok. + */ + if (domount){ + int f = fork(); + if (f < 0) + errx(1, "fork!"); + if (!f){ + char *addr, *aport; + int port; + char options[128]; + + port = getaddr(mountaddr, &addr, &aport); + sprintf(options, "port=%d,noextend", port); + if (mymount(addr, "/tmp/cache", mountflags, options) < 0) + errx(1, "Mount failed"); + } + + } + + if (mountonly) + exit(0); + + ixp_serverloop(&server); + printf("msg %s\n", ixp_errbuf()); + return ret; +} + diff --git a/include/Makefile b/include/Makefile @@ -1,5 +1,6 @@ ROOT= .. include ${ROOT}/mk/hdr.mk +include ${ROOT}/mk/ixp.mk HFILES = ixp.h ixp_fcall.h diff --git a/include/ixp.h b/include/ixp.h @@ -7,25 +7,40 @@ #include <sys/types.h> #include <sys/select.h> +/* Gunk */ #undef uchar -#define uchar _ixpuchar #undef ushort -#define ushort _ixpushort #undef uint -#define uint _ixpuint #undef ulong -#define ulong _ixpulong #undef vlong -#define vlong _ixpvlong #undef uvlong +#define uchar _ixpuchar +#define ushort _ixpushort +#define uint _ixpuint +#define ulong _ixpulong +#define vlong _ixpvlong #define uvlong _ixpuvlong + +#ifdef KENCC +# define STRUCT(x) struct {x}; +# define UNION(x) union {x}; +#elif defined(__GNUC__) && !defined(IXPlint) +# define STRUCT(x) __extension__ struct {x}; +# define UNION(x) __extension__ union {x}; +#else +# define STRUCT(x) x +# define UNION(x) x +#endif +/* End Gunk */ + typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; typedef unsigned long ulong; -typedef long long vlong; typedef unsigned long long uvlong; +typedef long long vlong; + #define IXP_VERSION "9P2000" #define IXP_NOTAG ((ushort)~0) /* Dummy tag */ #define IXP_NOFID (~0U) @@ -147,6 +162,7 @@ enum { # define RStat P9_RStat # define TWStat P9_TWStat # define RWStat P9_RWStat +# # define OREAD P9_OREAD # define OWRITE P9_OWRITE # define ORDWR P9_ORDWR @@ -159,6 +175,7 @@ enum { # define OEXCL P9_OEXCL # define OLOCK P9_OLOCK # define OAPPEND P9_OAPPEND +# # define QTDIR P9_QTDIR # define QTAPPEND P9_QTAPPEND # define QTEXCL P9_QTEXCL @@ -173,6 +190,7 @@ enum { # define DMMOUNT P9_DMMOUNT # define DMAUTH P9_DMAUTH # define DMTMP P9_DMTMP +# # define DMSYMLINK P9_DMSYMLINK # define DMDEVICE P9_DMDEVICE # define DMNAMEDPIPE P9_DMNAMEDPIPE @@ -228,36 +246,89 @@ struct IxpRendez { enum { MsgPack, MsgUnpack, }; struct IxpMsg { - uchar *data; - uchar *pos; - uchar *end; - uint size; - uint mode; + char *data; + char *pos; + char *end; + uint size; + uint mode; }; struct IxpQid { - uchar type; - uint version; - uvlong path; + uchar type; + ulong version; + uvlong path; /* internal use only */ - uchar dir_type; + uchar dir_type; }; -#include <ixp_fcall.h> +/* from fcall(3) in plan9port */ +struct IxpFcall { + uchar type; + ushort tag; + ulong fid; + + UNION ( + STRUCT ( /* Tversion, Rversion */ + ulong msize; + char *version; + ) + STRUCT ( /* Tflush */ + ushort oldtag; + ) + STRUCT ( /* Rerror */ + char *ename; + ) + STRUCT ( /* Ropen, Rcreate */ + IxpQid qid; /* +Rattach */ + ulong iounit; + ) + STRUCT ( /* Rauth */ + IxpQid aqid; + ) + STRUCT ( /* Tauth, Tattach */ + ulong afid; + char *uname; + char *aname; + ) + STRUCT ( /* Tcreate */ + ulong perm; + char *name; + uchar mode; /* +Topen */ + ) + STRUCT ( /* Twalk */ + ulong newfid; + ushort nwname; + char *wname[IXP_MAX_WELEM]; + ) + STRUCT ( /* Rwalk */ + ushort nwqid; + IxpQid wqid[IXP_MAX_WELEM]; + ) + STRUCT ( + uvlong offset; /* Tread, Twrite */ + ulong count; /* Tread, Twrite, Rread */ + char *data; /* Twrite, Rread */ + ) + STRUCT ( /* Twstat, Rstat */ + ushort nstat; + uchar *stat; + ) + ) +}; /* stat structure */ struct IxpStat { - ushort type; - uint dev; - IxpQid qid; - uint mode; - uint atime; - uint mtime; - uvlong length; - char *name; - char *uid; - char *gid; - char *muid; + ushort type; + ulong dev; + IxpQid qid; + ulong mode; + ulong atime; + ulong mtime; + uvlong length; + char *name; + char *uid; + char *gid; + char *muid; }; struct IxpConn { @@ -273,23 +344,23 @@ struct IxpConn { }; struct IxpServer { - IxpConn *conn; - void (*preselect)(IxpServer*); - void *aux; - int running; - int maxfd; - fd_set rd; + IxpConn *conn; + void (*preselect)(IxpServer*); + void *aux; + int running; + int maxfd; + fd_set rd; }; struct IxpRpc { - IxpClient *mux; - IxpRpc *next; - IxpRpc *prev; - IxpRendez r; - uint tag; - IxpFcall *p; - int waiting; - int async; + IxpClient *mux; + IxpRpc *next; + IxpRpc *prev; + IxpRendez r; + uint tag; + IxpFcall *p; + int waiting; + int async; }; struct IxpClient { @@ -298,21 +369,21 @@ struct IxpClient { uint lastfid; /* Implementation details */ - uint nwait; - uint mwait; - uint freetag; - IxpCFid *freefid; - IxpMsg rmsg; - IxpMsg wmsg; - IxpMutex lk; - IxpMutex rlock; - IxpMutex wlock; - IxpRendez tagrend; - IxpRpc **wait; - IxpRpc *muxer; - IxpRpc sleep; - int mintag; - int maxtag; + uint nwait; + uint mwait; + uint freetag; + IxpCFid *freefid; + IxpMsg rmsg; + IxpMsg wmsg; + IxpMutex lk; + IxpMutex rlock; + IxpMutex wlock; + IxpRendez tagrend; + IxpRpc **wait; + IxpRpc *muxer; + IxpRpc sleep; + int mintag; + int maxtag; }; struct IxpCFid { @@ -370,36 +441,36 @@ struct Ixp9Srv { struct IxpThread { /* RWLock */ - int (*initrwlock)(IxpRWLock*); - void (*rlock)(IxpRWLock*); - int (*canrlock)(IxpRWLock*); - void (*runlock)(IxpRWLock*); - void (*wlock)(IxpRWLock*); - int (*canwlock)(IxpRWLock*); - void (*wunlock)(IxpRWLock*); - void (*rwdestroy)(IxpRWLock*); + int (*initrwlock)(IxpRWLock*); + void (*rlock)(IxpRWLock*); + int (*canrlock)(IxpRWLock*); + void (*runlock)(IxpRWLock*); + void (*wlock)(IxpRWLock*); + int (*canwlock)(IxpRWLock*); + void (*wunlock)(IxpRWLock*); + void (*rwdestroy)(IxpRWLock*); /* Mutex */ - int (*initmutex)(IxpMutex*); - void (*lock)(IxpMutex*); - int (*canlock)(IxpMutex*); - void (*unlock)(IxpMutex*); - void (*mdestroy)(IxpMutex*); + int (*initmutex)(IxpMutex*); + void (*lock)(IxpMutex*); + int (*canlock)(IxpMutex*); + void (*unlock)(IxpMutex*); + void (*mdestroy)(IxpMutex*); /* Rendez */ - int (*initrendez)(IxpRendez*); - void (*sleep)(IxpRendez*); - int (*wake)(IxpRendez*); - int (*wakeall)(IxpRendez*); - void (*rdestroy)(IxpRendez*); + int (*initrendez)(IxpRendez*); + void (*sleep)(IxpRendez*); + int (*wake)(IxpRendez*); + int (*wakeall)(IxpRendez*); + void (*rdestroy)(IxpRendez*); /* Other */ - char *(*errbuf)(void); - ssize_t (*read)(int, void*, size_t); - ssize_t (*write)(int, const void*, size_t); - int (*select)(int, fd_set*, fd_set*, fd_set*, struct timeval*); + char *(*errbuf)(void); + ssize_t (*read)(int, void*, size_t); + ssize_t (*write)(int, const void*, size_t); + int (*select)(int, fd_set*, fd_set*, fd_set*, struct timeval*); }; extern IxpThread *ixp_thread; -extern int (*ixp_vsnprint)(char*, int, char*, va_list); -extern char* (*ixp_vsmprint)(char*, va_list); +extern int (*ixp_vsnprint)(char*, int, const char*, va_list); +extern char* (*ixp_vsmprint)(const char*, va_list); /* thread_*.c */ int ixp_taskinit(void); @@ -407,79 +478,79 @@ int ixp_rubyinit(void); int ixp_pthread_init(void); #ifdef VARARGCK -# pragma varargck argpos ixp_print 2 -# pragma varargck argpos ixp_werrstr 1 -# pragma varargck argpos ixp_eprint 1 +# pragma varargck argpos ixp_print 2 +# pragma varargck argpos ixp_werrstr 1 +# pragma varargck argpos ixp_eprint 1 #endif /* client.c */ -IxpClient *ixp_mount(char *address); -IxpClient *ixp_mountfd(int fd); -void ixp_unmount(IxpClient *c); -IxpCFid *ixp_create(IxpClient *c, char *name, uint perm, uchar mode); -IxpCFid *ixp_open(IxpClient *c, char *name, uchar mode); -int ixp_remove(IxpClient *c, char *path); -IxpStat *ixp_stat(IxpClient *c, char *path); -long ixp_read(IxpCFid *f, void *buf, long count); -long ixp_write(IxpCFid *f, void *buf, long count); -long ixp_pread(IxpCFid *f, void *buf, long count, vlong offset); -long ixp_pwrite(IxpCFid *f, void *buf, long count, vlong offset); -int ixp_close(IxpCFid *f); -int ixp_print(IxpCFid *f, char *fmt, ...); -int ixp_vprint(IxpCFid *f, char *fmt, va_list ap); +IxpClient* ixp_mount(char*); +IxpClient* ixp_mountfd(int); +void ixp_unmount(IxpClient*); +IxpCFid* ixp_create(IxpClient*, char*, uint perm, uchar mode); +IxpCFid* ixp_open(IxpClient*, char*, uchar); +int ixp_remove(IxpClient*, char*); +IxpStat* ixp_stat(IxpClient*, char*); +long ixp_read(IxpCFid*, void*, long); +long ixp_write(IxpCFid*, const void*, long); +long ixp_pread(IxpCFid*, void*, long, vlong); +long ixp_pwrite(IxpCFid*, const void*, long, vlong); +int ixp_close(IxpCFid*); +int ixp_print(IxpCFid*, const char*, ...); +int ixp_vprint(IxpCFid*, const char*, va_list); /* convert.c */ -void ixp_pu8(IxpMsg *msg, uchar *val); -void ixp_pu16(IxpMsg *msg, ushort *val); -void ixp_pu32(IxpMsg *msg, uint *val); -void ixp_pu64(IxpMsg *msg, uvlong *val); -void ixp_pdata(IxpMsg *msg, char **data, uint len); -void ixp_pstring(IxpMsg *msg, char **s); -void ixp_pstrings(IxpMsg *msg, ushort *num, char *strings[]); -void ixp_pqid(IxpMsg *msg, IxpQid *qid); -void ixp_pqids(IxpMsg *msg, ushort *num, IxpQid qid[]); -void ixp_pstat(IxpMsg *msg, IxpStat *stat); +void ixp_pu8(IxpMsg*, uchar*); +void ixp_pu16(IxpMsg*, ushort*); +void ixp_pu32(IxpMsg*, ulong*); +void ixp_pu64(IxpMsg*, uvlong*); +void ixp_pdata(IxpMsg*, char**, uint); +void ixp_pstring(IxpMsg*, char**); +void ixp_pstrings(IxpMsg*, ushort*, char**); +void ixp_pqid(IxpMsg*, IxpQid*); +void ixp_pqids(IxpMsg*, ushort*, IxpQid*); +void ixp_pstat(IxpMsg*, IxpStat*); /* error.h */ char *ixp_errbuf(void); void ixp_errstr(char*, int); void ixp_rerrstr(char*, int); -void ixp_werrstr(char*, ...); +void ixp_werrstr(const char*, ...); /* request.c */ -void respond(Ixp9Req *r, char *error); -void serve_9pcon(IxpConn *c); +void respond(Ixp9Req*, const char *err); +void serve_9pcon(IxpConn*); /* message.c */ -ushort ixp_sizeof_stat(IxpStat *stat); -IxpMsg ixp_message(uchar *data, uint length, uint mode); -void ixp_freestat(IxpStat *s); -void ixp_freefcall(IxpFcall *fcall); -uint ixp_msg2fcall(IxpMsg *msg, IxpFcall *fcall); -uint ixp_fcall2msg(IxpMsg *msg, IxpFcall *fcall); +ushort ixp_sizeof_stat(IxpStat*); +IxpMsg ixp_message(uchar*, uint len, uint mode); +void ixp_freestat(IxpStat*); +void ixp_freefcall(IxpFcall*); +uint ixp_msg2fcall(IxpMsg*, IxpFcall*); +uint ixp_fcall2msg(IxpMsg*, IxpFcall*); /* server.c */ -IxpConn *ixp_listen(IxpServer *s, int fd, void *aux, - void (*read)(IxpConn *c), - void (*close)(IxpConn *c)); -void ixp_hangup(IxpConn *c); -int ixp_serverloop(IxpServer *s); -void ixp_server_close(IxpServer *s); +IxpConn* ixp_listen(IxpServer*, int, void*, + void (*read)(IxpConn*), + void (*close)(IxpConn*)); +void ixp_hangup(IxpConn*); +int ixp_serverloop(IxpServer*); +void ixp_server_close(IxpServer*); /* socket.c */ -int ixp_dial(char *address); -int ixp_announce(char *address); +int ixp_dial(char*); +int ixp_announce(char*); /* transport.c */ -uint ixp_sendmsg(int fd, IxpMsg *msg); -uint ixp_recvmsg(int fd, IxpMsg *msg); +uint ixp_sendmsg(int, IxpMsg*); +uint ixp_recvmsg(int, IxpMsg*); /* util.c */ -void *ixp_emalloc(uint size); -void *ixp_emallocz(uint size); -void *ixp_erealloc(void *ptr, uint size); -char *ixp_estrdup(const char *str); -void ixp_eprint(const char *fmt, ...); -uint ixp_tokenize(char **result, uint reslen, char *str, char delim); -uint ixp_strlcat(char *dst, const char *src, uint siz); +void* ixp_emalloc(uint); +void* ixp_emallocz(uint); +void* ixp_erealloc(void*, uint); +char* ixp_estrdup(const char*); +void ixp_eprint(const char*, ...); +uint ixp_tokenize(char**, uint len, char*, char); +uint ixp_strlcat(char*, const char*, uint); diff --git a/include/ixp_local.h b/include/ixp_local.h @@ -2,6 +2,22 @@ #define IXP_P9_STRUCTS #include <ixp.h> +char *argv0; +#define ARGBEGIN int _argi, _argtmp, _inargv=0; char *_argv; \ + if(!argv0)argv0=ARGF(); _inargv=1; \ + while(argc && argv[0][0] == '-') { \ + _argi=1; _argv=*argv++; argc--; \ + while(_argv[_argi]) switch(_argv[_argi++]) +#define ARGEND }_inargv=0;USED(_argtmp);USED(_argv);USED(_argi) +#define ARGF() ((_inargv && _argv[_argi]) ? \ + (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \ + : ((argc > 0) ? (argc--, *argv++) : ((char*)0))) +#define EARGF(f) ((_inargv && _argv[_argi]) ? \ + (_argtmp=_argi, _argi=strlen(_argv), _argv+_argtmp) \ + : ((argc > 0) ? (argc--, *argv++) : ((f), (char*)0))) +#define USED(x) if(x){}else +#define SET(x) ((x)=0) + #define thread ixp_thread #define eprint ixp_eprint @@ -42,17 +58,16 @@ struct Intmap { #define caninsertkey ixp_caninsertkey /* intmap.c */ -void initmap(Intmap *m, ulong nhash, void *hash); -void incref_map(Intmap *m); -void decref_map(Intmap *m); -void freemap(Intmap *map, void (*destroy)(void*)); -void execmap(Intmap *map, void (*destroy)(void*)); -void *lookupkey(Intmap *map, ulong id); -void *insertkey(Intmap *map, ulong id, void *v); -void *deletekey(Intmap *map, ulong id); -int caninsertkey(Intmap *map, ulong id, void *v); +void initmap(Intmap*, ulong, void*); +void incref_map(Intmap*); +void decref_map(Intmap*); +void freemap(Intmap*, void (*destroy)(void*)); +void execmap(Intmap*, void (*destroy)(void*)); +void *lookupkey(Intmap*, ulong); +void *insertkey(Intmap*, ulong, void*); +void *deletekey(Intmap*, ulong); +int caninsertkey(Intmap*, ulong, void*); #undef nil #define nil ((void*)0) -#define USED(v) if(v){}else{} diff --git a/libixp/Makefile b/libixp/Makefile @@ -3,8 +3,6 @@ include ${ROOT}/mk/hdr.mk include ${ROOT}/mk/ixp.mk TARG = libixp -FCALL_H = $(ROOT)/include/ixp_fcall.h -HFILES = $(FCALL_H) OBJ = client \ convert \ @@ -21,7 +19,3 @@ OBJ = client \ include ${ROOT}/mk/lib.mk -$(FCALL_H): fcall.h${FCALL_H_VERSION} ${ROOT}/config.mk - echo HEADER $$($(CLEANNAME) $(BASE)/$(FCALL_H)) from fcall.h${FCALL_H_VERSION} - cp fcall.h${FCALL_H_VERSION} $(FCALL_H) - diff --git a/libixp/client.c b/libixp/client.c @@ -415,7 +415,7 @@ ixp_pread(IxpCFid *f, void *buf, long count, vlong offset) { } static long -_pwrite(IxpCFid *f, void *buf, long count, vlong offset) { +_pwrite(IxpCFid *f, const void *buf, long count, vlong offset) { Fcall fcall; int n, len; @@ -425,7 +425,7 @@ _pwrite(IxpCFid *f, void *buf, long count, vlong offset) { fcall.type = TWrite; fcall.fid = f->fid; fcall.offset = f->offset; - fcall.data = buf + len; + fcall.data = (char*)buf + len; fcall.count = n; if(dofcall(f->client, &fcall) == 0) return -1; @@ -441,7 +441,7 @@ _pwrite(IxpCFid *f, void *buf, long count, vlong offset) { } long -ixp_write(IxpCFid *f, void *buf, long count) { +ixp_write(IxpCFid *f, const void *buf, long count) { int n; thread->lock(&f->iolock); @@ -453,7 +453,7 @@ ixp_write(IxpCFid *f, void *buf, long count) { } long -ixp_pwrite(IxpCFid *f, void *buf, long count, vlong offset) { +ixp_pwrite(IxpCFid *f, const void *buf, long count, vlong offset) { int n; thread->lock(&f->iolock); @@ -463,7 +463,7 @@ ixp_pwrite(IxpCFid *f, void *buf, long count, vlong offset) { } int -ixp_vprint(IxpCFid *f, char *fmt, va_list ap) { +ixp_vprint(IxpCFid *f, const char *fmt, va_list ap) { char *buf; int n; @@ -477,7 +477,7 @@ ixp_vprint(IxpCFid *f, char *fmt, va_list ap) { } int -ixp_print(IxpCFid *f, char *fmt, ...) { +ixp_print(IxpCFid *f, const char *fmt, ...) { va_list ap; int n; diff --git a/libixp/convert.c b/libixp/convert.c @@ -14,33 +14,35 @@ enum { }; void -ixp_puint(IxpMsg *msg, uint size, uint *val) { +ixp_puint(IxpMsg *msg, uint size, ulong *val) { + uchar *pos; int v; if(msg->pos + size <= msg->end) { + pos = msg->pos; switch(msg->mode) { case MsgPack: v = *val; switch(size) { case SDWord: - msg->pos[3] = v>>24; - msg->pos[2] = v>>16; + pos[3] = v>>24; + pos[2] = v>>16; case SWord: - msg->pos[1] = v>>8; + pos[1] = v>>8; case SByte: - msg->pos[0] = v; + pos[0] = v; break; } case MsgUnpack: v = 0; switch(size) { case SDWord: - v |= msg->pos[3]<<24; - v |= msg->pos[2]<<16; + v |= pos[3]<<24; + v |= pos[2]<<16; case SWord: - v |= msg->pos[1]<<8; + v |= pos[1]<<8; case SByte: - v |= msg->pos[0]; + v |= pos[0]; break; } *val = v; @@ -50,12 +52,12 @@ ixp_puint(IxpMsg *msg, uint size, uint *val) { } void -ixp_pu32(IxpMsg *msg, uint *val) { +ixp_pu32(IxpMsg *msg, ulong *val) { ixp_puint(msg, SDWord, val); } void ixp_pu8(IxpMsg *msg, uchar *val) { - uint v; + ulong v; v = *val; ixp_puint(msg, SByte, &v); @@ -63,7 +65,7 @@ ixp_pu8(IxpMsg *msg, uchar *val) { } void ixp_pu16(IxpMsg *msg, ushort *val) { - uint v; + ulong v; v = *val; ixp_puint(msg, SWord, &v); @@ -71,7 +73,7 @@ ixp_pu16(IxpMsg *msg, ushort *val) { } void ixp_pu64(IxpMsg *msg, uvlong *val) { - uint vl, vb; + ulong vl, vb; vl = (uint)*val; vb = (uint)(*val>>32); @@ -101,7 +103,7 @@ ixp_pstring(IxpMsg *msg, char **s) { void ixp_pstrings(IxpMsg *msg, ushort *num, char *strings[]) { - uchar *s; + char *s; uint i, size; ushort len; diff --git a/libixp/error.c b/libixp/error.c @@ -6,12 +6,12 @@ #include "ixp_local.h" static int -_vsnprint(char *buf, int n, char *fmt, va_list ap) { +_vsnprint(char *buf, int n, const char *fmt, va_list ap) { return vsnprintf(buf, n, fmt, ap); } static char* -_vsmprint(char *fmt, va_list ap) { +_vsmprint(const char *fmt, va_list ap) { va_list al; char *buf = ""; int n; @@ -26,8 +26,8 @@ _vsmprint(char *fmt, va_list ap) { return buf; } -int (*ixp_vsnprint)(char*, int, char*, va_list) = _vsnprint; -char* (*ixp_vsmprint)(char*, va_list) = _vsmprint; +int (*ixp_vsnprint)(char*, int, const char*, va_list) = _vsnprint; +char* (*ixp_vsmprint)(const char*, va_list) = _vsmprint; /* Approach to errno handling taken from Plan 9 Port. */ enum { @@ -62,7 +62,7 @@ rerrstr(char *buf, int n) { } void -werrstr(char *fmt, ...) { +werrstr(const char *fmt, ...) { char tmp[IXP_ERRMAX]; va_list ap; diff --git a/libixp/fcall.h b/libixp/fcall.h @@ -1,54 +0,0 @@ -/* from fcall(3) in plan9port */ -struct IxpFcall { - uchar type; - ushort tag; - uint fid; - union { - struct { /* Tversion, Rversion */ - uint msize; - char *version; - }; - struct { /* Tflush */ - ushort oldtag; - }; - struct { /* Rerror */ - char *ename; - }; - struct { /* Ropen, Rcreate */ - IxpQid qid; /* +Rattach */ - uint iounit; - }; - struct { /* Rauth */ - IxpQid aqid; - }; - struct { /* Tauth, Tattach */ - uint afid; - char *uname; - char *aname; - }; - struct { /* Tcreate */ - uint perm; - char *name; - uchar mode; /* +Topen */ - }; - struct { /* Twalk */ - uint newfid; - ushort nwname; - char *wname[IXP_MAX_WELEM]; - }; - struct { /* Rwalk */ - ushort nwqid; - IxpQid wqid[IXP_MAX_WELEM]; - }; - struct { /* Twrite */ - uvlong offset; /* +Tread */ - /* +Rread */ - uint count; /* +Tread */ - char *data; - }; - struct { /* Twstat, Rstat */ - ushort nstat; - uchar *stat; - }; - }; -}; diff --git a/libixp/fcall.h.nounion b/libixp/fcall.h.nounion @@ -1,53 +0,0 @@ -/* from fcall(3) in plan9port */ -struct IxpFcall { - uchar type; - ushort tag; - uint fid; - - /* Tversion, Rversion */ - uint msize; - char *version; - - /* Tflush */ - ushort oldtag; - - /* Rerror */ - char *ename; - - /* Ropen, Rcreate */ - IxpQid qid; /* +Rattach */ - uint iounit; - - /* Rauth */ - IxpQid aqid; - - /* Tauth, Tattach */ - uint afid; - char *uname; - char *aname; - - /* Tcreate */ - uint perm; - char *name; - uchar mode; /* +Topen */ - - /* Twalk */ - uint newfid; - ushort nwname; - char *wname[IXP_MAX_WELEM]; - - /* Rwalk */ - ushort nwqid; - IxpQid wqid[IXP_MAX_WELEM]; - - /* Twrite */ - uvlong offset; /* +Tread */ - - /* +Rread */ - uint count; /* +Tread */ - char *data; - - /* Twstat, Rstat */ - ushort nstat; - uchar *stat; -}; diff --git a/libixp/ixp_fcall.h b/libixp/ixp_fcall.h @@ -1,53 +0,0 @@ -/* from fcall(3) in plan9port */ -struct IxpFcall { - uchar type; - ushort tag; - uint fid; - - /* Tversion, Rversion */ - uint msize; - char *version; - - /* Tflush */ - ushort oldtag; - - /* Rerror */ - char *ename; - - /* Ropen, Rcreate */ - IxpQid qid; /* +Rattach */ - uint iounit; - - /* Rauth */ - IxpQid aqid; - - /* Tauth, Tattach */ - uint afid; - char *uname; - char *aname; - - /* Tcreate */ - uint perm; - char *name; - uchar mode; /* +Topen */ - - /* Twalk */ - uint newfid; - ushort nwname; - char *wname[IXP_MAX_WELEM]; - - /* Rwalk */ - ushort nwqid; - IxpQid wqid[IXP_MAX_WELEM]; - - /* Twrite */ - uvlong offset; /* +Tread */ - - /* +Rread */ - uint count; /* +Tread */ - char *data; - - /* Twstat, Rstat */ - ushort nstat; - uchar *stat; -}; diff --git a/libixp/message.c b/libixp/message.c @@ -169,7 +169,7 @@ ixp_pfcall(IxpMsg *msg, Fcall *fcall) { uint ixp_fcall2msg(IxpMsg *msg, Fcall *fcall) { - uint size; + ulong size; msg->end = msg->data + msg->size; msg->pos = msg->data + SDWord; diff --git a/libixp/request.c b/libixp/request.c @@ -307,7 +307,7 @@ handlereq(Ixp9Req *r) { } void -respond(Ixp9Req *r, char *error) { +respond(Ixp9Req *r, const char *error) { Ixp9Conn *pc; int msize; @@ -389,7 +389,7 @@ respond(Ixp9Req *r, char *error) { r->ofcall.type = r->ifcall.type + 1; else { r->ofcall.type = RError; - r->ofcall.ename = error; + r->ofcall.ename = (char*)error; } deletekey(&pc->tagmap, r->ifcall.tag);; diff --git a/libixp/socket.c b/libixp/socket.c @@ -1,5 +1,5 @@ -/* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * Copyright ©2007 Kris Maglione <fbsdaemon@gmail.com> +/* Copyright ©2007 Kris Maglione <fbsdaemon@gmail.com> + * Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com> * See LICENSE file for license details. */ #include <errno.h> @@ -47,7 +47,7 @@ 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)); diff --git a/libixp/transport.c b/libixp/transport.c @@ -70,7 +70,7 @@ ixp_sendmsg(int fd, IxpMsg *msg) { uint ixp_recvmsg(int fd, IxpMsg *msg) { enum { SSize = 4 }; - uint msize, size; + ulong msize, size; msg->mode = MsgUnpack; msg->pos = msg->data; diff --git a/man/Makefile b/man/Makefile @@ -1,5 +1,6 @@ ROOT=.. include ${ROOT}/mk/hdr.mk +include ${ROOT}/mk/ixp.mk TARG = ixpc.1 diff --git a/mk/gcc.mk b/mk/gcc.mk @@ -7,7 +7,6 @@ CFLAGS += \ -Wno-switch \ -Wno-comment \ -Wno-sign-compare \ - -Wno-uninitialized \ -Wno-unused-parameter \ -Wimplicit \ -Wreturn-type \ diff --git a/mk/hdr.mk b/mk/hdr.mk @@ -13,8 +13,8 @@ all: ${LINK} $@ $< .c.O: - ${COMPILE} $@ $< - ${LINK} $@ $< + ${COMPILE} ${<:.c=.o} $< + ${LINK} $@ ${<:.c=.o} .awk.O: echo FILTER ${BASE}$< diff --git a/mk/ixp.mk b/mk/ixp.mk @@ -1 +1,4 @@ VERSION = 0.3 + +${ROOT}/include/ixp.h: ${ROOT}/config.mk + diff --git a/test/client.c b/test/client.c @@ -3,11 +3,18 @@ #include <bio.h> #include <thread.h> #include <ixp.h> -#include <ixp_pthread.h> extern char *(*_syserrstr)(void); char *path; +enum { + DATA = 1, + THREAD = 2, + TRACE = 4, + READ = 8, +}; +int chatty = READ; + typedef struct arg arg; typedef struct arg2 arg2; struct arg { @@ -24,126 +31,161 @@ struct arg2 { int j; }; +Channel *chan; +int nproc; + +void +spawn(void(*f)(void*), void *v, int s) { + nproc++; + proccreate(f, v, s); +} + +void +_print(Biobuf *b, char *p, char *end, int j, int k) { + for(; p < end; p++) { + Bputc(b, *p); + if(*p == '\n') { + Bflush(b); + Bprint(b, ":: %d %d: ", j, k); + } + } +} + void readfile(IxpCFid *f, int j, int k) { Biobuf *b; - char *buf, *p, *end; + char *buf; int n; - fprint(2, "readfile(%p, %d, %d) iounit: %d\n", f, j, k, f->iounit); + if(chatty&TRACE) + fprint(2, "readfile(%p, %d, %d) iounit: %d\n", f, j, k, f->iounit); - b = Bfdopen(1, OWRITE); - Bprint(b, ":: %d %d: ", j, k); + b = Bfdopen(dup(1, -1), OWRITE); + if(chatty&DATA) + Bprint(b, ":: %d %d: ", j, k); buf = ixp_emalloc(f->iounit); while((n = ixp_read(f, buf, f->iounit)) > 0) { - fprint(2, "+readfile(%p, %d, %d) n=%d\n", f, j, k, n); - end = buf+n; - p = buf; - for(p = buf; p < end; p++) { - Bputc(b, *p); - if(*p == '\n') { - Bflush(b); - Bprint(b, ":: %d %d: ", j, k); - } - } + if(chatty&READ) + fprint(2, "+readfile(%p, %d, %d) n=%d\n", f, j, k, n); + if(chatty&DATA) + _print(b, buf, buf+n, j, k); + sleep(0); } - fprint(2, "-readfile(%p, %d, %d) iounit: %d\n", f, j, k, f->iounit); - Bputc(b, '\n'); + if(chatty&TRACE) + fprint(2, "-readfile(%p, %d, %d) iounit: %d\n", f, j, k, f->iounit); + if(chatty&DATA) + Bputc(b, '\n'); Bterm(b); } static void _read(void *p) { arg *a; - int i, k; + int k; a = p; k = a->k; - print("Start _read: %d\n", a->j, k); + if(chatty&THREAD) + print("Start _read: %d\n", a->j, k); qlock(a->r.l); sendul(a->ch, 0); rsleep(&a->r); - print("Wake _read: %d\n", a->j, k); + if(chatty&THREAD) + print("Wake _read: %d\n", a->j, k); qunlock(a->r.l); - for(i = 0; i < 15; i++) - readfile(a->f, a->j, k); + readfile(a->f, a->j, k); + sendul(chan, 0); } static void _open(void *p) { arg2 *a2; - arg a; + arg *a; + + a = malloc(sizeof *a); a2 = p; - a.j = a2->j; - memset(&a.r, 0, sizeof(a.r)); - a.r.l = mallocz(sizeof(QLock), 1); - a.ch = chancreate(sizeof(ulong), 0); - print("Start _open: %d\n", a2->j); + a->j = a2->j; + memset(&a->r, 0, sizeof(a->r)); + a->r.l = mallocz(sizeof(QLock), 1); + a->ch = chancreate(sizeof(ulong), 0); + + if(chatty&THREAD) + print("Start _open: %d\n", a2->j); qlock(a2->r.l); sendul(a2->ch, 0); rsleep(&a2->r); - print("Wake _open: %d\n", a2->j); + if(chatty&THREAD) + print("Wake _open: %d\n", a2->j); qunlock(a2->r.l); - a.f = ixp_open(a2->c, path, OREAD); - if(a.f == nil) + a->f = ixp_open(a2->c, path, OREAD); + if(a->f == nil) sysfatal("can't open %q: %r\n", path); + sleep(0); - for(a.k = 0; a.k < 5; a.k++) { - proccreate(_read, &a, mainstacksize); - recvul(a.ch); + for(a->k = 0; a->k < 5; a->k++) { + spawn(_read, a, mainstacksize); + recvul(a->ch); } - qlock(a.r.l); - rwakeupall(&a.r); - qunlock(a.r.l); - recvul(chancreate(sizeof(ulong),0)); + qlock(a->r.l); + rwakeupall(&a->r); + qunlock(a->r.l); + + sendul(chan, 0); } const char *_malloc_options = "A"; void threadmain(int argc, char *argv[]) { - arg2 a; + arg2 *a; char *address; - USED(argc); - USED(argv); + USED(argc, argv); address = "unix!/tmp/ns.kris.:0/wmii"; address = "tcp!localhost!6663"; path = "/n/local/var/log/messages"; + a = malloc(sizeof *a); + chan = chancreate(sizeof(ulong), 0); + quotefmtinstall(); _syserrstr = ixp_errbuf; if(ixp_pthread_init()) sysfatal("can't init pthread: %r\n"); - a.c = ixp_mount(address); - if(a.c == nil) + a->c = ixp_mount(address); + if(a->c == nil) sysfatal("can't mount: %r\n"); - memset(&a.r, 0, sizeof(a.r)); - a.r.l = mallocz(sizeof(QLock), 1); - a.ch = chancreate(sizeof(ulong), 0); - for(a.j = 0; a.j < 5; a.j++) { - proccreate(_open, &a, mainstacksize); - recvul(a.ch); + memset(&a->r, 0, sizeof(a->r)); + a->r.l = mallocz(sizeof(QLock), 1); + a->ch = chancreate(sizeof(ulong), 0); + for(a->j = 0; a->j < 5; a->j++) { + spawn(_open, a, mainstacksize); + recvul(a->ch); } - qlock(a.r.l); - fprint(2, "qlock()\n"); - rwakeupall(&a.r); - fprint(2, "wokeup\n"); - qunlock(a.r.l); - fprint(2, "unlocked\n"); - recvul(chancreate(sizeof(ulong),0)); + qlock(a->r.l); + if(chatty&THREAD) + fprint(2, "qlock()\n"); + rwakeupall(&a->r); + if(chatty&THREAD) + fprint(2, "wokeup\n"); + qunlock(a->r.l); + if(chatty&THREAD) + fprint(2, "unlocked\n"); + + while(nproc--) + recvul(chan); } diff --git a/test/mkfile b/test/mkfile @@ -2,8 +2,8 @@ default:V: all -CFLAGS=-I../include -O0 -LDFLAGS=-L../libixp -L../libixp_pthread -lixp -lixp_pthread +CFLAGS=-I../include +LDFLAGS=-L../lib -lixp -lixp_pthread TARG=\ client\ diff --git a/test/o.client b/test/o.client Binary files differ. diff --git a/util/compile b/util/compile @@ -8,6 +8,7 @@ bin="$(echo $0 | sed 's,/[^/]*$,,')" xtmp=/tmp/cc.$$.$USER.out echo CC $($bin/cleanname ${BASE}$outfile) +[ -n "$noisycc" ] && echo $CC -o $outfile $CFLAGS $@ $CC -o $outfile $CFLAGS $@ 2>$xtmp status=$? diff --git a/util/link b/util/link @@ -21,6 +21,7 @@ done xtmp=/tmp/ld.$$.$USER.out echo LD "$($bin/cleanname ${BASE}$outfile)" +[ -n "$noisycc" ] && echo $LD -o $outfile $ofiles $LDFLAGS $args $LD -o $outfile $ofiles $LDFLAGS $args >$xtmp 2>&1 status=$?