libixp

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

commit 23cf68f97519220b25e2ef60fe964968e418cbe2
parent 758aab6ce4130bdb4ec99cdaf8c714b1a2c8a761
Author: Kris Maglione <kris@suckless.org>
Date:   Tue, 15 Jun 2010 14:22:44 -0400

First stab at API man pages.

Diffstat:
.hgignore | 4++--
Makefile | 6++++++
include/ixp.h | 35+++++++++++++++++++----------------
lib/libixp/client.c | 188++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
lib/libixp/error.c | 25++++++++++++++-----------
lib/libixp/server.c | 73++++++++++++++++++++++++++++++++++++++-----------------------------------
lib/libixp/socket.c | 15++++++++-------
lib/libixp/srv_util.c | 43++++++++++++++++++++++++++++++++-----------
lib/libixp/thread.c | 4++--
lib/libixp/timer.c | 60+++++++++++++++++++++++++++++++++---------------------------
lib/libixp/util.c | 15+++++++++------
man/Makefile | 6+++++-
man/header.t2t | 13+++++++++++++
man/ixp_close.3 | 28++++++++++++++++++++++++++++
man/ixp_dial.3 | 40++++++++++++++++++++++++++++++++++++++++
man/ixp_errbuf.3 | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_hangup.3 | 29+++++++++++++++++++++++++++++
man/ixp_listen.3 | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_mount.3 | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_msec.3 | 20++++++++++++++++++++
man/ixp_namespace.3 | 35+++++++++++++++++++++++++++++++++++
man/ixp_nexttimer.3 | 30++++++++++++++++++++++++++++++
man/ixp_open.3 | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_read.3 | 45+++++++++++++++++++++++++++++++++++++++++++++
man/ixp_remove.3 | 32++++++++++++++++++++++++++++++++
man/ixp_serverloop.3 | 43+++++++++++++++++++++++++++++++++++++++++++
man/ixp_settimer.3 | 42++++++++++++++++++++++++++++++++++++++++++
man/ixp_srv_clonefiles.3 | 24++++++++++++++++++++++++
man/ixp_srv_data2cstring.3 | 24++++++++++++++++++++++++
man/ixp_srv_freefile.3 | 24++++++++++++++++++++++++
man/ixp_srv_getfile.3 | 35+++++++++++++++++++++++++++++++++++
man/ixp_stat.3 | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_unmount.3 | 23+++++++++++++++++++++++
man/ixp_unsettimer.3 | 33+++++++++++++++++++++++++++++++++
man/ixp_vprint.3 | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
man/ixp_write.3 | 46++++++++++++++++++++++++++++++++++++++++++++++
man/targets.mk | 24++++++++++++++++++++++++
mk/common.mk | 14++++++++++++++
mk/gcc.mk | 4++--
mk/hdr.mk | 22+++++++++++-----------
mk/lib.mk | 2+-
mk/man.mk | 24++++++++++++++++++++++--
mk/so.mk | 2+-
test/client.c | 4++--
util/compile | 6+++---
util/grepdoc | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
util/link | 4++--
47 files changed, 1445 insertions(+), 221 deletions(-)

diff --git a/.hgignore b/.hgignore @@ -1,10 +1,10 @@ syntax: regexp (^|/)\.((.*\.)?sw.|depend|hgignore)$ (^|/)(tags|mkfile|diff)$ -\.([oa]|out|o_pic|so|pyc|pyo|diff)$ +\.([oa]|out|o_pic|so|pyc|pyo|diff|man3)$ \.(diff|orig|rej|bak)$ \.(aux|idx|ilg|ind|log|toc)$ -^(pkg|src)/ +^(pkg|src|doc)/ /bak/ syntax: glob config.local.mk diff --git a/Makefile b/Makefile @@ -6,5 +6,11 @@ DIRS = lib \ include \ man +doc: + perl $(ROOT)/util/grepdoc $$(hg manifest | egrep '^(lib|include)') \ + >$(ROOT)/man/targets.mk + $(MAKE) -Cman + +.PHONY: doc include $(ROOT)/mk/dir.mk diff --git a/include/ixp.h b/include/ixp.h @@ -66,7 +66,8 @@ enum { }; /* 9P message types */ -enum { P9_TVersion = 100, +enum IxpFType { + P9_TVersion = 100, P9_RVersion, P9_TAuth = 102, P9_RAuth, @@ -97,7 +98,8 @@ enum { P9_TVersion = 100, }; /* from libc.h in p9p */ -enum { P9_OREAD = 0, /* open for read */ +enum IxpOMode { + P9_OREAD = 0, /* open for read */ P9_OWRITE = 1, /* write */ P9_ORDWR = 2, /* read and write */ P9_OEXEC = 3, /* execute, == read but check execute permission */ @@ -111,8 +113,9 @@ enum { P9_OREAD = 0, /* open for read */ P9_OAPPEND = 0x4000 /* or'ed in, append only */ }; -/* bits in Qid.type */ -enum { P9_QTDIR = 0x80, /* type bit for directories */ +/* bits in IxpQid.type */ +enum IxpQType { + P9_QTDIR = 0x80, /* type bit for directories */ P9_QTAPPEND = 0x40, /* type bit for append only files */ P9_QTEXCL = 0x20, /* type bit for exclusive use files */ P9_QTMOUNT = 0x10, /* type bit for mounted channel */ @@ -122,14 +125,12 @@ enum { P9_QTDIR = 0x80, /* type bit for directories */ P9_QTFILE = 0x00 /* type bits for plain file */ }; -/* bits in Dir.mode */ -enum { +/* bits in IxpStat.mode */ +enum IxpDMode { P9_DMEXEC = 0x1, /* mode bit for execute permission */ P9_DMWRITE = 0x2, /* mode bit for write permission */ P9_DMREAD = 0x4, /* mode bit for read permission */ -}; -/* Larger than int, can't be enum */ #define P9_DMDIR 0x80000000 /* mode bit for directories */ #define P9_DMAPPEND 0x40000000 /* mode bit for append only files */ #define P9_DMEXCL 0x20000000 /* mode bit for exclusive use files */ @@ -142,6 +143,7 @@ enum { #define P9_DMSOCKET 0x00100000 /* mode bit for socket (Unix, 9P2000.u) */ #define P9_DMSETUID 0x00080000 /* mode bit for setuid (Unix, 9P2000.u) */ #define P9_DMSETGID 0x00040000 /* mode bit for setgid (Unix, 9P2000.u) */ +}; #ifdef IXP_NO_P9_ # define TVersion P9_TVersion @@ -267,7 +269,7 @@ struct IxpQid { uchar type; ulong version; uvlong path; - /* internal use only */ + /* Private members */ uchar dir_type; }; @@ -377,8 +379,8 @@ struct IxpFTWStat { }; #if defined(IXP_NEEDAPI) && IXP_NEEDAPI <= 89 /* from fcall(3) in plan9port */ -typedef struct IxpFcall IxpFcall; -struct IxpFcall { +typedef struct IxpFcall IxpFcall; /* Deprecated */ +struct IxpFcall { /* Deprecated */ uchar type; ushort tag; ulong fid; @@ -471,7 +473,7 @@ struct IxpConn { void (*close)(IxpConn *); char closed; - /* Implementation details, do not use */ + /* Private members */ IxpConn *next; }; @@ -502,7 +504,7 @@ struct IxpClient { uint msize; uint lastfid; - /* Implementation details */ + /* Private members */ uint nwait; uint mwait; uint freetag; @@ -528,7 +530,8 @@ struct IxpCFid { uint iounit; uvlong offset; IxpClient* client; - /* internal use only */ + + /* Private members */ IxpCFid* next; IxpMutex iolock; }; @@ -541,7 +544,7 @@ struct IxpFid { signed char omode; uint iounit; - /* Implementation details */ + /* Private members */ Ixp9Conn* conn; IxpMap* map; }; @@ -555,7 +558,7 @@ struct Ixp9Req { IxpFcall ofcall; void* aux; - /* Implementation details */ + /* Private members */ Ixp9Conn *conn; }; diff --git a/lib/libixp/client.c b/lib/libixp/client.c @@ -89,25 +89,28 @@ fail: /** * Function: ixp_unmount * - * Unmounts the client P<c> and frees its data structures. + * Unmounts the client P<client> and frees its data structures. + * + * See also: + * F<ixp_mount> */ void -ixp_unmount(IxpClient *c) { +ixp_unmount(IxpClient *client) { IxpCFid *f; - shutdown(c->fd, SHUT_RDWR); - close(c->fd); + shutdown(client->fd, SHUT_RDWR); + close(client->fd); - muxfree(c); + muxfree(client); - while((f = c->freefid)) { - c->freefid = f->next; + while((f = client->freefid)) { + client->freefid = f->next; thread->mdestroy(&f->iolock); free(f); } - free(c->rmsg.data); - free(c->wmsg.data); - free(c); + free(client->rmsg.data); + free(client->wmsg.data); + free(client); } static void @@ -119,17 +122,18 @@ allocmsg(IxpClient *c, int n) { } /** - * Function: ixp_mountfd * Function: ixp_mount + * Function: ixp_mountfd * Function: ixp_nsmount + * Type: IxpClient * * Params: - * fd - A file descriptor which is already connected - * to a 9P server. - * address - An address (in Plan 9 resource fomat) at - * which to connect to a 9P server. - * name - The name of a socket in the process's canonical - * namespace directory. + * fd: A file descriptor which is already connected + * to a 9P server. + * address: An address (in Plan 9 resource fomat) at + * which to connect to a 9P server. + * name: The name of a socket in the process's canonical + * namespace directory. * * Initiate a 9P connection with the server at P<address>, * connected to on P<fd>, or under the process's namespace @@ -137,6 +141,8 @@ allocmsg(IxpClient *c, int n) { * * Returns: * A pointer to a new 9P client. + * See also: + * F<ixp_unmount> */ IxpClient* @@ -293,12 +299,14 @@ clunk(IxpCFid *f) { * Function: ixp_remove * * Params: - * path - The path of the file to remove. + * path: The path of the file to remove. * * Removes a file or directory from the remote server. * * Returns: * ixp_remove returns 0 on failure, 1 on success. + * See also: + * F<ixp_mount> */ int @@ -330,25 +338,30 @@ initfid(IxpCFid *f, Fcall *fcall) { } /** - * Function: ixp_create * Function: ixp_open + * Function: ixp_create + * Type: IxpCFid + * Type: IxpOMode * * Params: - * path - The path of the file to open or create. - * perm - The permissions with which to create the new - * file. These will be ANDed with those of the - * parent directory by the server. - * mode - The file's open mode. + * path: The path of the file to open or create. + * perm: The permissions with which to create the new + * file. These will be ANDed with those of the + * parent directory by the server. + * mode: The file's open mode. * * ixp_open and ixp_create each open a file at P<path>. * P<mode> must include OREAD, OWRITE, or ORDWR, and may - * include any of the modes specified in 9pmodes(3). + * include any of the modes specified in T<IxpOMode>. * ixp_create, additionally, creates a file at P<path> if it * doesn't already exist. * * Returns: * A pointer on which to operate on the newly - * opened file. + * opened file. + * + * See also: + * F<ixp_mount>, F<ixp_read>, F<ixp_write>, F<ixp_close> */ IxpCFid* @@ -418,6 +431,8 @@ ixp_open(IxpClient *c, const char *path, uchar mode) { * * Returns: * Returns 1 on success, and zero on failure. + * See also: + * F<ixp_mount>, F<ixp_open> */ int @@ -451,18 +466,22 @@ _stat(IxpClient *c, ulong fid) { /** * Function: ixp_stat * Function: ixp_fstat + * Type: IxpStat + * Type: IxpQid + * Type: IxpQType + * Type: IxpDMode * * Params: - * path - The path of the file to stat. - * f - A CFid of an open file to stat. + * path: The path of the file to stat. + * fid: An open file descriptor to stat. * - * Stats the file at P<path> or pointed to by P<f>. + * Stats the file at P<path> or pointed to by P<fid>. * * Returns: - * Returns a Stat structure, which must be freed by - * the caller with free(3). - * - * S<Stat> + * Returns an IxpStat structure, which must be freed by + * the caller with free(3). + * See also: + * F<ixp_mount>, F<ixp_open> */ Stat* @@ -480,8 +499,8 @@ ixp_stat(IxpClient *c, const char *path) { } Stat* -ixp_fstat(IxpCFid *f) { - return _stat(f->client, f->fid); +ixp_fstat(IxpCFid *fid) { + return _stat(fid->client, fid->fid); } static long @@ -518,40 +537,42 @@ _pread(IxpCFid *f, char *buf, long count, vlong offset) { * Function: ixp_pread * * Params: - * buf - A buffer in which to store the read data. - * count - The number of bytes to read. - * offset - The offset at which to begin reading. + * buf: A buffer in which to store the read data. + * count: The number of bytes to read. + * offset: The offset at which to begin reading. * * ixp_read and ixp_pread each read P<count> bytes of data - * from the file pointed to by P<f>, into P<buf>. ixp_read + * from the file pointed to by P<fid>, into P<buf>. ixp_read * begins reading at its stored offset, and increments it by * the number of bytes read. ixp_pread reads beginning at - * P<offset> and does not alter C<f>'s stored offset. + * P<offset> and does not alter P<fid>'s stored offset. * * Returns: * These functions return the number of bytes read on - * success and -1 on failure. + * success and -1 on failure. + * See also: + * F<ixp_mount>, F<ixp_open>, F<ixp_write> */ long -ixp_read(IxpCFid *f, void *buf, long count) { +ixp_read(IxpCFid *fid, void *buf, long count) { int n; - thread->lock(&f->iolock); - n = _pread(f, buf, count, f->offset); + thread->lock(&fid->iolock); + n = _pread(fid, buf, count, fid->offset); if(n > 0) - f->offset += n; - thread->unlock(&f->iolock); + fid->offset += n; + thread->unlock(&fid->iolock); return n; } long -ixp_pread(IxpCFid *f, void *buf, long count, vlong offset) { +ixp_pread(IxpCFid *fid, void *buf, long count, vlong offset) { int n; - thread->lock(&f->iolock); - n = _pread(f, buf, count, offset); - thread->unlock(&f->iolock); + thread->lock(&fid->iolock); + n = _pread(fid, buf, count, offset); + thread->unlock(&fid->iolock); return n; } @@ -586,41 +607,43 @@ _pwrite(IxpCFid *f, const void *buf, long count, vlong offset) { * Function: ixp_pwrite * * Params: - * buf - A buffer holding the contents to store. - * count - The number of bytes to store. - * offset - The offset at which to write the data. + * buf: A buffer holding the contents to store. + * count: The number of bytes to store. + * offset: The offset at which to write the data. * * ixp_write and ixp_pwrite each write P<count> bytes of - * data stored in P<buf> to the file pointed to by C<f>. + * data stored in P<buf> to the file pointed to by C<fid>. * ixp_write writes its data at its stored offset, and * increments it by P<count>. ixp_pwrite writes its data a - * P<offset> and does not alter C<f>'s stored offset. + * P<offset> and does not alter C<fid>'s stored offset. * * Returns: * These functions return the number of bytes actually - * written. Any value less than P<count> must be considered - * a failure. + * written. Any value less than P<count> must be considered + * a failure. + * See also: + * F<ixp_mount>, F<ixp_open>, F<ixp_read> */ long -ixp_write(IxpCFid *f, const void *buf, long count) { +ixp_write(IxpCFid *fid, const void *buf, long count) { int n; - thread->lock(&f->iolock); - n = _pwrite(f, buf, count, f->offset); + thread->lock(&fid->iolock); + n = _pwrite(fid, buf, count, fid->offset); if(n > 0) - f->offset += n; - thread->unlock(&f->iolock); + fid->offset += n; + thread->unlock(&fid->iolock); return n; } long -ixp_pwrite(IxpCFid *f, const void *buf, long count, vlong offset) { +ixp_pwrite(IxpCFid *fid, const void *buf, long count, vlong offset) { int n; - thread->lock(&f->iolock); - n = _pwrite(f, buf, count, offset); - thread->unlock(&f->iolock); + thread->lock(&fid->iolock); + n = _pwrite(fid, buf, count, offset); + thread->unlock(&fid->iolock); return n; } @@ -630,45 +653,52 @@ ixp_pwrite(IxpCFid *f, const void *buf, long count, vlong offset) { * Variable: ixp_vsmprint * * Params: - * fmt - The string with which to format the data. - * ap - A va_list holding the arguments to the format - * string. - * ... - The arguments to the format string. + * fid: An open IxpCFid to which to write the result. + * fmt: The string with which to format the data. + * args: A va_list holding the arguments to the format + * string. + * ...: The arguments to the format string. * * These functions act like the standard formatted IO * functions. They write the result of the formatting to the - * file pointed to by C<f>. + * file pointed to by C<fid>. * * V<ixp_vsmprint> may be set to a function which will - * format its arguments and return a null terminated string - * allocated with malloc(3). + * format its arguments and return a nul-terminated string + * allocated by malloc(3). The default formats its arguments as + * printf(3). The function must format '%s' as a nul-terminated + * string and may not consume any arguments not specified by a + * %-prefixed format specifier, but may otherwise behave in any + * manner chosen by the user. * * Returns: * These functions return the number of bytes written. - * There is currently no way to detect failure. + * There is currently no way to detect failure. + * See also: + * F<ixp_mount>, F<ixp_open>, printf(3) */ int -ixp_vprint(IxpCFid *f, const char *fmt, va_list ap) { +ixp_vprint(IxpCFid *fid, const char *fmt, va_list args) { char *buf; int n; - buf = ixp_vsmprint(fmt, ap); + buf = ixp_vsmprint(fmt, args); if(buf == nil) return -1; - n = ixp_write(f, buf, strlen(buf)); + n = ixp_write(fid, buf, strlen(buf)); free(buf); return n; } int -ixp_print(IxpCFid *f, const char *fmt, ...) { +ixp_print(IxpCFid *fid, const char *fmt, ...) { va_list ap; int n; va_start(ap, fmt); - n = ixp_vprint(f, fmt, ap); + n = ixp_vprint(fid, fmt, ap); va_end(ap); return n; diff --git a/lib/libixp/error.c b/lib/libixp/error.c @@ -42,10 +42,10 @@ enum { * Function: ixp_werrstr * * Params: - * buf - The buffer to read and/or fill. - * n - The size of the buffer. - * fmt - A format string with which to write the * errstr. - * ... - Arguments to P<fmt>. + * buf: The buffer to read and/or fill. + * size: The size of the buffer. + * fmt: A format string with which to write the errstr. + * ...: Arguments to P<fmt>. * * These functions simulate Plan 9's errstr functionality. * They replace errno in libixp. Note that these functions @@ -55,12 +55,15 @@ enum { * thread. F<ixp_rerrstr> fills P<buf> with the data from * the current thread's error buffer, while F<ixp_errstr> * exchanges P<buf>'s contents with those of the current - * thread's error buffer. F<ixp_werrstr> is takes a format - * string from which to construct an errstr. + * thread's error buffer. F<ixp_werrstr> formats the given + * format string, P<fmt>, via V<ixp_vsmprint> and writes it to + * the error buffer. * * Returns: * F<ixp_errbuf> returns the current thread's error - * string buffer. + * string buffer. + * See also: + * V<ixp_vsmprint> */ char* ixp_errbuf() { @@ -75,18 +78,18 @@ ixp_errbuf() { } void -errstr(char *buf, int n) { +errstr(char *buf, int size) { char tmp[IXP_ERRMAX]; strncpy(tmp, buf, sizeof tmp); - rerrstr(buf, n); + rerrstr(buf, size); strncpy(thread->errbuf(), tmp, IXP_ERRMAX); errno = EPLAN9; } void -rerrstr(char *buf, int n) { - strncpy(buf, ixp_errbuf(), n); +rerrstr(char *buf, int size) { + strncpy(buf, ixp_errbuf(), size); } void diff --git a/lib/libixp/server.c b/lib/libixp/server.c @@ -1,3 +1,4 @@ +/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail> /* Copyright ©2004-2006 Anselm R. Garbe <garbeam at gmail dot com> * See LICENSE file for license details. */ @@ -11,41 +12,40 @@ /** * Function: ixp_listen + * Type: IxpConn * * Params: - * fs - The file descriptor on which to listen. - * aux - A piece of data to store in the connection's - * T<IxpConn> data structure. - * read - The function to call when the connection has + * fs: The file descriptor on which to listen. + * aux: A piece of data to store in the connection's + * S<IxpConn> data structure. + * read: The function to call when the connection has * data available to read. - * close - A cleanup function to call when the - * connection is closed. + * close: A cleanup function to call when the + * connection is closed. * - * Starts the server P<s> listening on P<fd>. The optional + * Starts the server P<srv> listening on P<fd>. The optional * callbacks are called as described, with the connections - * T<IxpConn> data structure as their arguments. + * S<IxpConn> data structure as their arguments. * * Returns: - * Returns the connection's new T<IxpConn> data - * structure. - * - * S<IxpConn> + * Returns the connection's new S<IxpConn> data + * structure. */ IxpConn* -ixp_listen(IxpServer *s, int fd, void *aux, - void (*read)(IxpConn *c), - void (*close)(IxpConn *c) +ixp_listen(IxpServer *srv, int fd, void *aux, + void (*read)(IxpConn*), + void (*close)(IxpConn*) ) { IxpConn *c; c = emallocz(sizeof *c); c->fd = fd; c->aux = aux; - c->srv = s; + c->srv = srv; c->read = read; c->close = close; - c->next = s->conn; - s->conn = c; + c->next = srv->conn; + srv->conn = c; return c; } @@ -58,6 +58,9 @@ ixp_listen(IxpServer *s, int fd, void *aux, * function, if it exists. ixp_server_close calls ixp_hangup * on all of the connections on which the server is * listening. + * + * See also: + * F<ixp_listen>, S<IxpServer>, S<IxpConn> */ void @@ -116,52 +119,52 @@ handle_conns(IxpServer *s) { /** * Function: ixp_serverloop + * Type: IxpServer * * Enters the main loop of the server. Exits when - * P<s>->running becomes false, or when select(2) returns an + * P<srv>->running becomes false, or when select(2) returns an * error other than EINTR. * - * S<IxpServer> - * * Returns: * Returns 0 when the loop exits normally, and 1 when - * it exits on error. V<errno> or the return value of - * ixp_errbuf(3) may be inspected. - * + * it exits on error. V<errno> or the return value of + * F<ixp_errbuf> may be inspected. + * See also: + * F<ixp_listen> */ int -ixp_serverloop(IxpServer *s) { +ixp_serverloop(IxpServer *srv) { timeval *tvp; timeval tv; long timeout; int r; - s->running = 1; - thread->initmutex(&s->lk); - while(s->running) { + srv->running = 1; + thread->initmutex(&srv->lk); + while(srv->running) { tvp = nil; - timeout = ixp_nexttimer(s); + timeout = ixp_nexttimer(srv); if(timeout > 0) { tv.tv_sec = timeout/1000; tv.tv_usec = timeout%1000 * 1000; tvp = &tv; } - if(s->preselect) - s->preselect(s); + if(srv->preselect) + srv->preselect(srv); - if(!s->running) + if(!srv->running) break; - prepare_select(s); - r = thread->select(s->maxfd + 1, &s->rd, 0, 0, tvp); + prepare_select(srv); + r = thread->select(srv->maxfd + 1, &srv->rd, 0, 0, tvp); if(r < 0) { if(errno == EINTR) continue; return 1; } - handle_conns(s); + handle_conns(srv); } return 0; } diff --git a/lib/libixp/socket.c b/lib/libixp/socket.c @@ -251,19 +251,20 @@ lookup(const char *address, addrtab *tab) { * Function: ixp_announce * * Params: - * address - An address on which to connect or listen, - * specified in the Plan 9 resources - * specification format - * (<protocol>!address[!<port>]) + * address: An address on which to connect or listen, + * specified in the Plan 9 resources + * specification format + * (<protocol>!address[!<port>]) * * These functions hide some of the ugliness of Berkely * Sockets. ixp_dial connects to the resource at P<address>, * while ixp_announce begins listening on P<address>. * * Returns: - * These functions return file descriptors on success, - * and -1 on failure. ixp_errbuf(3) may be inspected on - * failure. + * These functions return file descriptors on success, and -1 + * on failure. ixp_errbuf(3) may be inspected on failure. + * See also: + * socket(2) */ int diff --git a/lib/libixp/srv_util.c b/lib/libixp/srv_util.c @@ -33,7 +33,13 @@ static IxpFileId* free_fileid; /* Utility Functions */ /** + * Function: ixp_srv_getfile + * Type: IxpFileId + * * Obtain an empty, reference counted IxpFileId struct. + * + * See also: + * F<ixp_srv_clonefiles>, F<ixp_srv_freefile> */ IxpFileId* ixp_srv_getfile(void) { @@ -59,32 +65,42 @@ ixp_srv_getfile(void) { } /** + * Function: ixp_srv_freefile + * * Decrease the reference count of the given IxpFileId, * and push it onto the free list when it reaches 0; + * + * See also: + * F<ixp_srv_getfile> */ void -ixp_srv_freefile(IxpFileId *f) { - if(--f->nref) +ixp_srv_freefile(IxpFileId *fileid) { + if(--fileid->nref) return; - free(f->tab.name); - f->next = free_fileid; - free_fileid = f; + free(fileid->tab.name); + fileid->next = free_fileid; + free_fileid = fileid; } /** + * Function: ixp_srv_clonefiles + * * Increase the reference count of every IxpFileId linked - * to 'f'. + * to P<fileid>. + * + * See also: + * F<ixp_srv_getfile> */ IxpFileId* -ixp_srv_clonefiles(IxpFileId *f) { +ixp_srv_clonefiles(IxpFileId *fileid) { IxpFileId *r; r = emalloc(sizeof *r); - memcpy(r, f, sizeof *r); + memcpy(r, fileid, sizeof *r); r->tab.name = estrdup(r->tab.name); r->nref = 1; - for(f=f->next; f; f=f->next) - assert(f->nref++); + for(fileid=fileid->next; fileid; fileid=fileid->next) + assert(fileid->nref++); return r; } @@ -134,8 +150,13 @@ ixp_srv_writebuf(Ixp9Req *req, char **buf, uint *len, uint max) { } /** - * Ensure that the data member of 'r' is null terminated, + * Function: ixp_srv_data2cstring + * + * Ensure that the data member of P<req> is null terminated, * removing any new line from its end. + * + * See also: + * S<Ixp9Req> */ void ixp_srv_data2cstring(Ixp9Req *req) { diff --git a/lib/libixp/thread.c b/lib/libixp/thread.c @@ -2,8 +2,8 @@ #include <unistd.h> #include "ixp_local.h" -static IxpThread ixp_nothread; -IxpThread*ixp_thread = &ixp_nothread; +static IxpThread ixp_nothread; +IxpThread* ixp_thread = &ixp_nothread; static char* errbuf(void) { diff --git a/lib/libixp/timer.c b/lib/libixp/timer.c @@ -6,8 +6,9 @@ #include <sys/time.h> #include "ixp_local.h" -/* This really needn't be threadsafe, as it has little use in - * threaded programs, but it is, nonetheless. +/* + * This really needn't be threadsafe, as it has little use in + * threaded programs, but it nonetheless is. */ static long lastid = 1; @@ -15,8 +16,7 @@ static long lastid = 1; /** * Function: ixp_msec * - * Returns: - * Returns the time since the Epoch in milliseconds. + * Returns the time since the Epoch in milliseconds. * Be aware that this may overflow. */ long @@ -32,10 +32,10 @@ ixp_msec(void) { * Function: ixp_settimer * * Params: - * msec - The timeout in milliseconds. - * fn - The function to call after P<msec> milliseconds - * have elapsed. - * aux - An arbitrary argument to pass to P<fn> when it + * msec: The timeout in milliseconds. + * fn: The function to call after P<msec> milliseconds + * have elapsed. + * aux: An arbitrary argument to pass to P<fn> when it * is called. * * Initializes a callback-based timer to be triggerred after @@ -44,9 +44,11 @@ ixp_msec(void) { * * Returns: * Returns the new timer's unique id number. + * See also: + * F<ixp_unsettimer>, F<ixp_serverloop> */ long -ixp_settimer(IxpServer *s, long msec, void (*fn)(long, void*), void *aux) { +ixp_settimer(IxpServer *srv, long msec, void (*fn)(long, void*), void *aux) { Timer **tp; Timer *t; long time; @@ -57,18 +59,18 @@ ixp_settimer(IxpServer *s, long msec, void (*fn)(long, void*), void *aux) { msec += time; t = emallocz(sizeof *t); - thread->lock(&s->lk); + thread->lock(&srv->lk); t->id = lastid++; t->msec = msec; t->fn = fn; t->aux = aux; - for(tp=&s->timer; *tp; tp=&tp[0]->link) + for(tp=&srv->timer; *tp; tp=&tp[0]->link) if(tp[0]->msec < msec) break; t->link = *tp; *tp = t; - thread->unlock(&s->lk); + thread->unlock(&srv->lk); return t->id; } @@ -76,28 +78,30 @@ ixp_settimer(IxpServer *s, long msec, void (*fn)(long, void*), void *aux) { * Function: ixp_unsettimer * * Params: - * id - The id number of the timer to void. + * id: The id number of the timer to void. * * Voids the timer identified by P<id>. * * Returns: * Returns true if a timer was stopped, false - * otherwise. + * otherwise. + * See also: + * F<ixp_settimer>, F<ixp_serverloop> */ int -ixp_unsettimer(IxpServer *s, long id) { +ixp_unsettimer(IxpServer *srv, long id) { Timer **tp; Timer *t; - thread->lock(&s->lk); - for(tp=&s->timer; (t=*tp); tp=&t->link) + thread->lock(&srv->lk); + for(tp=&srv->timer; (t=*tp); tp=&t->link) if(t->id == id) break; if(t) { *tp = t->link; free(t); } - thread->unlock(&s->lk); + thread->unlock(&srv->lk); return t != nil; } @@ -105,35 +109,37 @@ ixp_unsettimer(IxpServer *s, long id) { * Function: ixp_nexttimer * * Triggers any timers whose timeouts have ellapsed. This is - * primarilly intended to be called from libixp's select + * primarily intended to be called from libixp's select * loop. * * Returns: * Returns the number of milliseconds until the next - * timer's timeout. + * timer's timeout. + * See also: + * F<ixp_settimer>, F<ixp_serverloop> */ long -ixp_nexttimer(IxpServer *s) { +ixp_nexttimer(IxpServer *srv) { Timer *t; long time, ret; SET(time); - thread->lock(&s->lk); - while((t = s->timer)) { + thread->lock(&srv->lk); + while((t = srv->timer)) { time = ixp_msec(); if(t->msec > time) break; - s->timer = t->link; + srv->timer = t->link; - thread->unlock(&s->lk); + thread->unlock(&srv->lk); t->fn(t->id, t->aux); free(t); - thread->lock(&s->lk); + thread->lock(&srv->lk); } ret = 0; if(t) ret = t->msec - time; - thread->unlock(&s->lk); + thread->unlock(&srv->lk); return ret; } diff --git a/lib/libixp/util.c b/lib/libixp/util.c @@ -1,4 +1,4 @@ -/* Written by Kris Maglione <fbsdaemon at gmail dot com> */ +/* Written by Kris Maglione <maglione.k at Gmail> */ /* Public domain */ #include <errno.h> #include <stdarg.h> @@ -84,9 +84,9 @@ ns_display(void) { if(!rmkdir(path, 0700)) ; else if(stat(path, &st)) - ixp_werrstr("Can't stat ns_path '%s': %s", path, ixp_errbuf()); + ixp_werrstr("Can't stat Namespace path '%s': %s", path, ixp_errbuf()); else if(getuid() != st.st_uid) - ixp_werrstr("ns_path '%s' exists but is not owned by you", path); + ixp_werrstr("Namespace 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: %s", path, ixp_errbuf()); else @@ -106,9 +106,12 @@ ns_display(void) { * 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. + * A statically allocated string which must not be freed + * or altered by the caller. The same value is returned + * upon successive calls. + * Bugs: + * This function is not thread safe until after its first + * call. */ /* Not especially threadsafe. */ char* diff --git a/man/Makefile b/man/Makefile @@ -2,6 +2,10 @@ ROOT=.. include $(ROOT)/mk/hdr.mk include $(ROOT)/mk/ixp.mk -TARG = ixpc.1 +include targets.mk +MANPAGES += ixpc.1 include $(ROOT)/mk/man.mk + +$(TARG): Makefile $(ROOT)/mk/ixp.mk header.t2t + diff --git a/man/header.t2t b/man/header.t2t @@ -0,0 +1,13 @@ +%!target: man +%!encoding: UTF-8 + +%!preproc: \bPROVISIONAL\b **PROVISIONAL** +%!preproc: [FSTV]<(.*?)> **\1(3)** +%!preproc: [P]<(.*?)> //\1// + +%!postproc(man): (\[.*?\]) \\fI\1\\fR +%!postproc(man): \+$ \n.P +%!postproc(man): (\$[a-zA-Z_]+) \\fB\1\\fR +%!postproc(man): (\${[a-zA-Z_]+)(.*?)} \\fB\1\\fR\2\\fB}\\fR +%!postproc(man): ^\.\.\.$ .RB ... + diff --git a/man/ixp_close.3 b/man/ixp_close.3 @@ -0,0 +1,28 @@ +.TH "IXP_CLOSE" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_close + +.SH SYNOPSIS +.nf + int ixp_close(IxpCFid *f); +.fi + +.SH DESCRIPTION +.P +Closes the file pointed to by \fIf\fR and frees its +associated data structures; + +.SH RETURN VALUE +.P +Returns 1 on success, and zero on failure. + +.SH SEE ALSO +.P +ixp_mount(3), ixp_open(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_close.man3 + diff --git a/man/ixp_dial.3 b/man/ixp_dial.3 @@ -0,0 +1,40 @@ +.TH "IXP_DIAL" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_dial, ixp_announce + +.SH SYNOPSIS +.nf + int ixp_dial(const char *address); + + int ixp_announce(const char *address); +.fi + +.SH PARAMETERS +.TP +address +An address on which to connect or listen, +specified in the Plan 9 resources +specification format +(<protocol>!address\fI[!<port>]\fR) + +.SH DESCRIPTION +.P +These functions hide some of the ugliness of Berkely +Sockets. ixp_dial connects to the resource at \fIaddress\fR, +while ixp_announce begins listening on \fIaddress\fR. + +.SH RETURN VALUE +.P +These functions return file descriptors on success, and \-1 +on failure. ixp_errbuf(3) may be inspected on failure. + +.SH SEE ALSO +.P +socket(2) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_dial.man3 + diff --git a/man/ixp_errbuf.3 b/man/ixp_errbuf.3 @@ -0,0 +1,59 @@ +.TH "IXP_ERRBUF" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_errbuf, ixp_errstr, ixp_rerrstr, ixp_werrstr + +.SH SYNOPSIS +.nf + char *ixp_errbuf(void); + + void ixp_errstr(char *buf, int size); + + void ixp_rerrstr(char *buf, int size); + + void ixp_werrstr(const char *fmt, ...); +.fi + +.SH PARAMETERS +.TP +buf +The buffer to read and/or fill. +.TP +size +The size of the buffer. +.TP +fmt +A format string with which to write the errstr. +.TP +.RB ... +Arguments to \fIfmt\fR. + +.SH DESCRIPTION +.P +These functions simulate Plan 9's errstr functionality. +They replace errno in libixp. Note that these functions +are not internationalized. + +.P +\fBixp_errbuf(3)\fR returns the errstr buffer for the current +thread. \fBixp_rerrstr(3)\fR fills \fIbuf\fR with the data from +the current thread's error buffer, while \fBixp_errstr(3)\fR +exchanges \fIbuf\fR's contents with those of the current +thread's error buffer. \fBixp_werrstr(3)\fR formats the given +format string, \fIfmt\fR, via \fBixp_vsmprint(3)\fR and writes it to +the error buffer. + +.SH RETURN VALUE +.P +\fBixp_errbuf(3)\fR returns the current thread's error +string buffer. + +.SH SEE ALSO +.P +ixp_vsmprint(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_errbuf.man3 + diff --git a/man/ixp_hangup.3 b/man/ixp_hangup.3 @@ -0,0 +1,29 @@ +.TH "IXP_HANGUP" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_hangup, ixp_server_close + +.SH SYNOPSIS +.nf + void ixp_hangup(IxpConn *c); + + void ixp_server_close(IxpServer *s); +.fi + +.SH DESCRIPTION +.P +ixp_hangup closes a connection, and stops the server +listening on it. It calls the connection's close +function, if it exists. ixp_server_close calls ixp_hangup +on all of the connections on which the server is +listening. + +.SH SEE ALSO +.P +ixp_listen(3), IxpServer(3), IxpConn(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_hangup.man3 + diff --git a/man/ixp_listen.3 b/man/ixp_listen.3 @@ -0,0 +1,56 @@ +.TH "IXP_LISTEN" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_listen, IxpConn + +.SH SYNOPSIS +.nf + IxpConn *ixp_listen(IxpServer *srv, int fd, void *aux, void (*read)(IxpConn *), void (*close)(IxpConn *)); + + typedef struct IxpConn IxpConn; + struct IxpConn { + IxpServer* srv; + void* aux; + int fd; + void (*read)(IxpConn *); + void (*close)(IxpConn *); + char closed; + + /* Private members */ + ... + } +.fi + +.SH PARAMETERS +.TP +fs +The file descriptor on which to listen. +.TP +aux +A piece of data to store in the connection's +\fBIxpConn(3)\fR data structure. +.TP +read +The function to call when the connection has +data available to read. +.TP +close +A cleanup function to call when the +connection is closed. + +.SH DESCRIPTION +.P +Starts the server \fIsrv\fR listening on \fIfd\fR. The optional +callbacks are called as described, with the connections +\fBIxpConn(3)\fR data structure as their arguments. + +.SH RETURN VALUE +.P +Returns the connection's new \fBIxpConn(3)\fR data +structure. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_listen.man3 + diff --git a/man/ixp_mount.3 b/man/ixp_mount.3 @@ -0,0 +1,57 @@ +.TH "IXP_MOUNT" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_mount, ixp_mountfd, ixp_nsmount, IxpClient + +.SH SYNOPSIS +.nf + IxpClient *ixp_mount(const char *address); + + IxpClient *ixp_mountfd(int fd); + + IxpClient *ixp_nsmount(const char *name); + + typedef struct IxpClient IxpClient; + struct IxpClient { + int fd; + uint msize; + uint lastfid; + + /* Private members */ + ... + } +.fi + +.SH PARAMETERS +.TP +fd +A file descriptor which is already connected +to a 9P server. +.TP +address +An address (in Plan 9 resource fomat) at +which to connect to a 9P server. +.TP +name +The name of a socket in the process's canonical +namespace directory. + +.SH DESCRIPTION +.P +Initiate a 9P connection with the server at \fIaddress\fR, +connected to on \fIfd\fR, or under the process's namespace +directory as \fIname\fR. + +.SH RETURN VALUE +.P +A pointer to a new 9P client. + +.SH SEE ALSO +.P +ixp_unmount(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_mount.man3 + diff --git a/man/ixp_msec.3 b/man/ixp_msec.3 @@ -0,0 +1,20 @@ +.TH "IXP_MSEC" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_msec + +.SH SYNOPSIS +.nf + long ixp_msec(void); +.fi + +.SH DESCRIPTION +.P +Returns the time since the Epoch in milliseconds. +Be aware that this may overflow. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_msec.man3 + diff --git a/man/ixp_namespace.3 b/man/ixp_namespace.3 @@ -0,0 +1,35 @@ +.TH "IXP_NAMESPACE" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_namespace + +.SH SYNOPSIS +.nf + char *ixp_namespace(void); +.fi + +.SH DESCRIPTION +.P +Returns the path of the canonical 9p namespace directory. +Either the value of \fB$NAMESPACE\fR, if it's set, or, roughly, +/tmp/ns.\fB${USER\fR\fB}\fR.\fB${DISPLAY\fR:%.0=%\fB}\fR. 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. + +.SH RETURN VALUE +.P +A statically allocated string which must not be freed +or altered by the caller. The same value is returned +upon successive calls. + +.SH BUGS +.P +This function is not thread safe until after its first +call. + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_namespace.man3 + diff --git a/man/ixp_nexttimer.3 b/man/ixp_nexttimer.3 @@ -0,0 +1,30 @@ +.TH "IXP_NEXTTIMER" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_nexttimer + +.SH SYNOPSIS +.nf + long ixp_nexttimer(IxpServer *srv); +.fi + +.SH DESCRIPTION +.P +Triggers any timers whose timeouts have ellapsed. This is +primarily intended to be called from libixp's select +loop. + +.SH RETURN VALUE +.P +Returns the number of milliseconds until the next +timer's timeout. + +.SH SEE ALSO +.P +ixp_settimer(3), ixp_serverloop(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_nexttimer.man3 + diff --git a/man/ixp_open.3 b/man/ixp_open.3 @@ -0,0 +1,76 @@ +.TH "IXP_OPEN" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_open, ixp_create, IxpCFid, IxpOMode + +.SH SYNOPSIS +.nf + IxpCFid *ixp_open(IxpClient *c, const char *path, uchar mode); + + IxpCFid *ixp_create(IxpClient *c, const char *path, uint perm, uchar mode); + + typedef struct IxpCFid IxpCFid; + struct IxpCFid { + uint fid; + IxpQid qid; + uchar mode; + uint open; + uint iounit; + uvlong offset; + IxpClient* client; + + /* Private members */ + ... + } + + enum IxpOMode { + P9_OREAD = 0, /* open for read */ + P9_OWRITE = 1, /* write */ + P9_ORDWR = 2, /* read and write */ + P9_OEXEC = 3, /* execute, == read but check execute permission */ + P9_OTRUNC = 16, /* or'ed in (except for exec), truncate file first */ + P9_OCEXEC = 32, /* or'ed in, close on exec */ + P9_ORCLOSE = 64, /* or'ed in, remove on close */ + P9_ODIRECT = 128, /* or'ed in, direct access */ + P9_ONONBLOCK = 256, /* or'ed in, non-blocking call */ + P9_OEXCL = 0x1000, /* or'ed in, exclusive use (create only) */ + P9_OLOCK = 0x2000, /* or'ed in, lock after opening */ + P9_OAPPEND = 0x4000 /* or'ed in, append only */ + } +.fi + +.SH PARAMETERS +.TP +path +The path of the file to open or create. +.TP +perm +The permissions with which to create the new +file. These will be ANDed with those of the +parent directory by the server. +.TP +mode +The file's open mode. + +.SH DESCRIPTION +.P +ixp_open and ixp_create each open a file at \fIpath\fR. +\fImode\fR must include OREAD, OWRITE, or ORDWR, and may +include any of the modes specified in \fBIxpOMode(3)\fR. +ixp_create, additionally, creates a file at \fIpath\fR if it +doesn't already exist. + +.SH RETURN VALUE +.P +A pointer on which to operate on the newly +opened file. + +.SH SEE ALSO +.P +ixp_mount(3), ixp_read(3), ixp_write(3), ixp_close(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_open.man3 + diff --git a/man/ixp_read.3 b/man/ixp_read.3 @@ -0,0 +1,45 @@ +.TH "IXP_READ" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_read, ixp_pread + +.SH SYNOPSIS +.nf + long ixp_read(IxpCFid *fid, void *buf, long count); + + long ixp_pread(IxpCFid *fid, void *buf, long count, vlong offset); +.fi + +.SH PARAMETERS +.TP +buf +A buffer in which to store the read data. +.TP +count +The number of bytes to read. +.TP +offset +The offset at which to begin reading. + +.SH DESCRIPTION +.P +ixp_read and ixp_pread each read \fIcount\fR bytes of data +from the file pointed to by \fIfid\fR, into \fIbuf\fR. ixp_read +begins reading at its stored offset, and increments it by +the number of bytes read. ixp_pread reads beginning at +\fIoffset\fR and does not alter \fIfid\fR's stored offset. + +.SH RETURN VALUE +.P +These functions return the number of bytes read on +success and \-1 on failure. + +.SH SEE ALSO +.P +ixp_mount(3), ixp_open(3), ixp_write(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_read.man3 + diff --git a/man/ixp_remove.3 b/man/ixp_remove.3 @@ -0,0 +1,32 @@ +.TH "IXP_REMOVE" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_remove + +.SH SYNOPSIS +.nf + int ixp_remove(IxpClient *c, const char *path); +.fi + +.SH PARAMETERS +.TP +path +The path of the file to remove. + +.SH DESCRIPTION +.P +Removes a file or directory from the remote server. + +.SH RETURN VALUE +.P +ixp_remove returns 0 on failure, 1 on success. + +.SH SEE ALSO +.P +ixp_mount(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_remove.man3 + diff --git a/man/ixp_serverloop.3 b/man/ixp_serverloop.3 @@ -0,0 +1,43 @@ +.TH "IXP_SERVERLOOP" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_serverloop, IxpServer + +.SH SYNOPSIS +.nf + int ixp_serverloop(IxpServer *srv); + + typedef struct IxpServer IxpServer; + struct IxpServer { + IxpConn* conn; + IxpMutex lk; + IxpTimer* timer; + void (*preselect)(IxpServer*); + void* aux; + int running; + int maxfd; + fd_set rd; + } +.fi + +.SH DESCRIPTION +.P +Enters the main loop of the server. Exits when +\fIsrv\fR\->running becomes false, or when select(2) returns an +error other than EINTR. + +.SH RETURN VALUE +.P +Returns 0 when the loop exits normally, and 1 when +it exits on error. \fBerrno(3)\fR or the return value of +\fBixp_errbuf(3)\fR may be inspected. + +.SH SEE ALSO +.P +ixp_listen(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_serverloop.man3 + diff --git a/man/ixp_settimer.3 b/man/ixp_settimer.3 @@ -0,0 +1,42 @@ +.TH "IXP_SETTIMER" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_settimer + +.SH SYNOPSIS +.nf + long ixp_settimer(IxpServer *srv, long msec, void (*fn)(long, void *), void *aux); +.fi + +.SH PARAMETERS +.TP +msec +The timeout in milliseconds. +.TP +fn +The function to call after \fImsec\fR milliseconds +have elapsed. +.TP +aux +An arbitrary argument to pass to \fIfn\fR when it +is called. + +.SH DESCRIPTION +.P +Initializes a callback\-based timer to be triggerred after +\fImsec\fR milliseconds. The timer is passed its id number +and the value of \fIaux\fR. + +.SH RETURN VALUE +.P +Returns the new timer's unique id number. + +.SH SEE ALSO +.P +ixp_unsettimer(3), ixp_serverloop(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_settimer.man3 + diff --git a/man/ixp_srv_clonefiles.3 b/man/ixp_srv_clonefiles.3 @@ -0,0 +1,24 @@ +.TH "IXP_SRV_CLONEFILES" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_srv_clonefiles + +.SH SYNOPSIS +.nf + IxpFileId *ixp_srv_clonefiles(IxpFileId *fileid); +.fi + +.SH DESCRIPTION +.P +Increase the reference count of every IxpFileId linked +to \fIfileid\fR. + +.SH SEE ALSO +.P +ixp_srv_getfile(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_srv_clonefiles.man3 + diff --git a/man/ixp_srv_data2cstring.3 b/man/ixp_srv_data2cstring.3 @@ -0,0 +1,24 @@ +.TH "IXP_SRV_DATA2CSTRING" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_srv_data2cstring + +.SH SYNOPSIS +.nf + void ixp_srv_data2cstring(Ixp9Req *req); +.fi + +.SH DESCRIPTION +.P +Ensure that the data member of \fIreq\fR is null terminated, +removing any new line from its end. + +.SH SEE ALSO +.P +Ixp9Req(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_srv_data2cstring.man3 + diff --git a/man/ixp_srv_freefile.3 b/man/ixp_srv_freefile.3 @@ -0,0 +1,24 @@ +.TH "IXP_SRV_FREEFILE" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_srv_freefile + +.SH SYNOPSIS +.nf + void ixp_srv_freefile(IxpFileId *fileid); +.fi + +.SH DESCRIPTION +.P +Decrease the reference count of the given IxpFileId, +and push it onto the free list when it reaches 0; + +.SH SEE ALSO +.P +ixp_srv_getfile(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_srv_freefile.man3 + diff --git a/man/ixp_srv_getfile.3 b/man/ixp_srv_getfile.3 @@ -0,0 +1,35 @@ +.TH "IXP_SRV_GETFILE" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_srv_getfile, IxpFileId + +.SH SYNOPSIS +.nf + IxpFileId *ixp_srv_getfile(void); + + typedef struct IxpFileId IxpFileId; + struct IxpFileId { + IxpFileId* next; + IxpFileIdU p; + bool pending; + uint id; + uint index; + IxpDirtab tab; + ushort nref; + uchar volatil; + } +.fi + +.SH DESCRIPTION +.P +Obtain an empty, reference counted IxpFileId struct. + +.SH SEE ALSO +.P +ixp_srv_clonefiles(3), ixp_srv_freefile(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_srv_getfile.man3 + diff --git a/man/ixp_stat.3 b/man/ixp_stat.3 @@ -0,0 +1,92 @@ +.TH "IXP_STAT" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_stat, ixp_fstat, IxpStat, IxpQid, IxpQType, IxpDMode + +.SH SYNOPSIS +.nf + Stat *ixp_stat(IxpClient *c, const char *path); + + Stat *ixp_fstat(IxpCFid *fid); + + typedef struct IxpStat IxpStat; + struct IxpStat { + ushort type; + ulong dev; + IxpQid qid; + ulong mode; + ulong atime; + ulong mtime; + uvlong length; + char* name; + char* uid; + char* gid; + char* muid; + } + + typedef struct IxpQid IxpQid; + struct IxpQid { + uchar type; + ulong version; + uvlong path; + /* Private members */ + ... + } + + enum IxpQType { + P9_QTDIR = 0x80, /* type bit for directories */ + P9_QTAPPEND = 0x40, /* type bit for append only files */ + P9_QTEXCL = 0x20, /* type bit for exclusive use files */ + P9_QTMOUNT = 0x10, /* type bit for mounted channel */ + P9_QTAUTH = 0x08, /* type bit for authentication file */ + P9_QTTMP = 0x04, /* type bit for non-backed-up file */ + P9_QTSYMLINK = 0x02, /* type bit for symbolic link */ + P9_QTFILE = 0x00 /* type bits for plain file */ + } + + enum IxpDMode { + P9_DMEXEC = 0x1, /* mode bit for execute permission */ + P9_DMWRITE = 0x2, /* mode bit for write permission */ + P9_DMREAD = 0x4, /* mode bit for read permission */ + + #define P9_DMDIR 0x80000000 /* mode bit for directories */ + #define P9_DMAPPEND 0x40000000 /* mode bit for append only files */ + #define P9_DMEXCL 0x20000000 /* mode bit for exclusive use files */ + #define P9_DMMOUNT 0x10000000 /* mode bit for mounted channel */ + #define P9_DMAUTH 0x08000000 /* mode bit for authentication file */ + #define P9_DMTMP 0x04000000 /* mode bit for non-backed-up file */ + #define P9_DMSYMLINK 0x02000000 /* mode bit for symbolic link (Unix, 9P2000.u) */ + #define P9_DMDEVICE 0x00800000 /* mode bit for device file (Unix, 9P2000.u) */ + #define P9_DMNAMEDPIPE 0x00200000 /* mode bit for named pipe (Unix, 9P2000.u) */ + #define P9_DMSOCKET 0x00100000 /* mode bit for socket (Unix, 9P2000.u) */ + #define P9_DMSETUID 0x00080000 /* mode bit for setuid (Unix, 9P2000.u) */ + #define P9_DMSETGID 0x00040000 /* mode bit for setgid (Unix, 9P2000.u) */ + } +.fi + +.SH PARAMETERS +.TP +path +The path of the file to stat. +.TP +fid +An open file descriptor to stat. + +.SH DESCRIPTION +.P +Stats the file at \fIpath\fR or pointed to by \fIfid\fR. + +.SH RETURN VALUE +.P +Returns an IxpStat structure, which must be freed by +the caller with free(3). + +.SH SEE ALSO +.P +ixp_mount(3), ixp_open(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_stat.man3 + diff --git a/man/ixp_unmount.3 b/man/ixp_unmount.3 @@ -0,0 +1,23 @@ +.TH "IXP_UNMOUNT" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_unmount + +.SH SYNOPSIS +.nf + void ixp_unmount(IxpClient *client); +.fi + +.SH DESCRIPTION +.P +Unmounts the client \fIclient\fR and frees its data structures. + +.SH SEE ALSO +.P +ixp_mount(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_unmount.man3 + diff --git a/man/ixp_unsettimer.3 b/man/ixp_unsettimer.3 @@ -0,0 +1,33 @@ +.TH "IXP_UNSETTIMER" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_unsettimer + +.SH SYNOPSIS +.nf + int ixp_unsettimer(IxpServer *srv, long id); +.fi + +.SH PARAMETERS +.TP +id +The id number of the timer to void. + +.SH DESCRIPTION +.P +Voids the timer identified by \fIid\fR. + +.SH RETURN VALUE +.P +Returns true if a timer was stopped, false +otherwise. + +.SH SEE ALSO +.P +ixp_settimer(3), ixp_serverloop(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_unsettimer.man3 + diff --git a/man/ixp_vprint.3 b/man/ixp_vprint.3 @@ -0,0 +1,57 @@ +.TH "IXP_VPRINT" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_vprint, ixp_print, ixp_vsmprint + +.SH SYNOPSIS +.nf + ixp_vprint + + int ixp_print(IxpCFid *fid, const char *fmt, ...); + + ixp_vsmprint +.fi + +.SH PARAMETERS +.TP +fid +An open IxpCFid to which to write the result. +.TP +fmt +The string with which to format the data. +.TP +args +A va_list holding the arguments to the format +string. +.TP +.RB ... +The arguments to the format string. + +.SH DESCRIPTION +.P +These functions act like the standard formatted IO +functions. They write the result of the formatting to the +file pointed to by C<fid>. + +.P +\fBixp_vsmprint(3)\fR may be set to a function which will +format its arguments and return a nul\-terminated string +allocated by malloc(3). The default formats its arguments as +printf(3). The function must format '%s' as a nul\-terminated +string and may not consume any arguments not specified by a +manner chosen by the user. + +.SH RETURN VALUE +.P +These functions return the number of bytes written. +There is currently no way to detect failure. + +.SH SEE ALSO +.P +ixp_mount(3), ixp_open(3), printf(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_vprint.man3 + diff --git a/man/ixp_write.3 b/man/ixp_write.3 @@ -0,0 +1,46 @@ +.TH "IXP_WRITE" 1 "2010 Jun" "libixp Manual" + +.SH NAME +.P +ixp_write, ixp_pwrite + +.SH SYNOPSIS +.nf + long ixp_write(IxpCFid *fid, const void *buf, long count); + + long ixp_pwrite(IxpCFid *fid, const void *buf, long count, vlong offset); +.fi + +.SH PARAMETERS +.TP +buf +A buffer holding the contents to store. +.TP +count +The number of bytes to store. +.TP +offset +The offset at which to write the data. + +.SH DESCRIPTION +.P +ixp_write and ixp_pwrite each write \fIcount\fR bytes of +data stored in \fIbuf\fR to the file pointed to by C<fid>. +ixp_write writes its data at its stored offset, and +increments it by \fIcount\fR. ixp_pwrite writes its data a +\fIoffset\fR and does not alter C<fid>'s stored offset. + +.SH RETURN VALUE +.P +These functions return the number of bytes actually +written. Any value less than \fIcount\fR must be considered +a failure. + +.SH SEE ALSO +.P +ixp_mount(3), ixp_open(3), ixp_read(3) + + +.\" man code generated by txt2tags 2.5 (http://txt2tags.sf.net) +.\" cmdline: txt2tags -o- ixp_write.man3 + diff --git a/man/targets.mk b/man/targets.mk @@ -0,0 +1,24 @@ +MANPAGES = \ + 'ixp_unmount.3' \ + 'ixp_mount.3 ixp_mountfd.3 ixp_nsmount.3 IxpClient.3' \ + 'ixp_remove.3' \ + 'ixp_open.3 ixp_create.3 IxpCFid.3 IxpOMode.3' \ + 'ixp_close.3' \ + 'ixp_stat.3 ixp_fstat.3 IxpStat.3 IxpQid.3 IxpQType.3 IxpDMode.3' \ + 'ixp_read.3 ixp_pread.3' \ + 'ixp_write.3 ixp_pwrite.3' \ + 'ixp_vprint.3 ixp_print.3 ixp_vsmprint.3' \ + 'ixp_errbuf.3 ixp_errstr.3 ixp_rerrstr.3 ixp_werrstr.3' \ + 'ixp_listen.3 IxpConn.3' \ + 'ixp_hangup.3 ixp_server_close.3' \ + 'ixp_serverloop.3 IxpServer.3' \ + 'ixp_dial.3 ixp_announce.3' \ + 'ixp_srv_getfile.3 IxpFileId.3' \ + 'ixp_srv_freefile.3' \ + 'ixp_srv_clonefiles.3' \ + 'ixp_srv_data2cstring.3' \ + 'ixp_msec.3' \ + 'ixp_settimer.3' \ + 'ixp_unsettimer.3' \ + 'ixp_nexttimer.3' \ + 'ixp_namespace.3' diff --git a/mk/common.mk b/mk/common.mk @@ -18,6 +18,20 @@ simpleinstall: $(INSTALL) -b 0755 $$f $(DIR) $$f; \ done +simpleuninstall: + for f in $(DOCS); do \ + $(UNINSTALL) $$f $(DOCDIR) $$f; \ + done + for f in $(TEXT); do \ + $(UNINSTALL) $$f $(DIR) $$f; \ + done + for f in $(BINARY); do \ + $(UNINSTALL) -b $$f $(DIR) $$f; \ + done + for f in $(EXECS); do \ + $(UNINSTALL) -b $$f $(DIR) $$f; \ + done + cleandep: echo CLEANDEP rm .depend 2>/dev/null || true diff --git a/mk/gcc.mk b/mk/gcc.mk @@ -1,6 +1,6 @@ DEBUGCFLAGS = \ -g \ - -O1 \ + -O0 \ -fno-builtin \ -fno-inline \ -fno-omit-frame-pointer \ @@ -8,7 +8,7 @@ DEBUGCFLAGS = \ -fno-unroll-loops CFLAGS += \ -std=c99 \ - -pedantic-errors \ + -pedantic \ -pipe \ -fno-strict-aliasing \ -Wall \ diff --git a/mk/hdr.mk b/mk/hdr.mk @@ -23,13 +23,13 @@ FILTER = cat EXCFLAGS = $(INCLUDES) -D_XOPEN_SOURCE=600 COMPILE_FLAGS = $(EXCFLAGS) $(CFLAGS) $$(pkg-config --cflags $(PACKAGES)) -COMPILE = $(ROOT)/util/compile "$(CC)" "$(COMPILE_FLAGS)" -COMPILEPIC = $(ROOT)/util/compile "$(CC)" "$(COMPILE_FLAGS) $(SOCFLAGS)" +COMPILE = $(SHELL) $(ROOT)/util/compile "$(CC)" "$(COMPILE_FLAGS)" +COMPILEPIC = $(SHELL) $(ROOT)/util/compile "$(CC)" "$(COMPILE_FLAGS) $(SOCFLAGS)" -LINK = $(ROOT)/util/link "$(LD)" "$$(pkg-config --libs $(PACKAGES)) $(LDFLAGS) $(LIBS)" -LINKSO = $(ROOT)/util/link "$(LD)" "$$(pkg-config --libs $(PACKAGES)) $(SOLDFLAGS) $(LIBS) $(SHARED)" +LINK = $(SHELL) $(ROOT)/util/link "$(LD)" "$$(pkg-config --libs $(PACKAGES)) $(LDFLAGS) $(LIBS)" +LINKSO = $(SHELL) $(ROOT)/util/link "$(LD)" "$$(pkg-config --libs $(PACKAGES)) $(SOLDFLAGS) $(LIBS) $(SHARED)" -CLEANNAME=$(ROOT)/util/cleanname +CLEANNAME=$(SHELL) $(ROOT)/util/cleanname SOEXT=so TAGFILES= @@ -56,7 +56,7 @@ MKCFG!=$(MKCFGSH) include $(MKCFG) .SILENT: -.SUFFIXES: .out .o .o_pic .c .pdf .sh .rc .$(SOEXT) .awk .1 .man1 .depend .install .uninstall .clean +.SUFFIXES: .out .o .o_pic .c .pdf .sh .rc .$(SOEXT) .awk .1 .3 .man1 .man3 .depend .install .uninstall .clean all: MAKEFILES=.depend @@ -65,7 +65,7 @@ MAKEFILES=.depend [ -n "$(noisycc)" ] && echo $(MKDEP) $(COMPILE_FLAGS) $< || true eval "$(MKDEP) $(COMPILE_FLAGS)" $< >>.depend -.sh.depend .rc.depend .1.depend .awk.depend: +.sh.depend .rc.depend .1.depend .3.depend .awk.depend: : .c.o: @@ -87,7 +87,7 @@ MAKEFILES=.depend $(FILTER) $< >$@; \ chmod 0755 $@ -.man1.1: +.man1.1 .man3.3: echo TXT2TAGS $(BASE)$< [ -n "$(noisycc)" ] && set -x; \ txt2tags -o- $< >$@ @@ -106,9 +106,9 @@ INSTALL= _install() { set -e; \ set +x; \ }; _install UNINSTALL= _uninstall() { set -e; \ - echo UNINSTALL $$($(CLEANNAME) $(BASE)$$2); \ + echo UNINSTALL $$($(CLEANNAME) $(BASE)$$1); \ [ -n "$(noisycc)" ] && set -x; \ - rm -f $(DESTDIR)$$3/$$(basename $$4); \ + rm -f $(DESTDIR)$$2/$$(basename $$3); \ }; _uninstall .out.install: @@ -137,7 +137,7 @@ MANSECTIONS=1 2 3 4 5 6 7 8 9 $(MANSECTIONS:%=.%.install): $(INSTALMAN) $< $(MANSECTIONS:%=.%.uninstall): - $(UNINSTALL) $< + $(UNINSTALLMAN) $< .out.clean: echo CLEAN $$($(CLEANNAME) $(BASE)$<) diff --git a/mk/lib.mk b/mk/lib.mk @@ -2,7 +2,7 @@ PTARG = $(ROOT)/lib/$(TARG) LIB = $(PTARG).a OFILES = $(OBJ:=.o) -all: $(HFILES) $(LIB) +all: $(HFILES) $(LIB) install: $(PTARG).install uninstall: $(PTARG).uninstall diff --git a/mk/man.mk b/mk/man.mk @@ -1,7 +1,27 @@ +targ = for k in $(MANPAGES); do echo $$k | sed 's/ .*//'; done +TARG := $(shell $(targ)) +TARG != $(targ) + all: $(TARG) -install: $(TARG:.1=.install) -uninstall: $(TARG:.1=.uninstall) +install: $(TARG:.1=.install) $(TARG:.3=.install) maninstall +uninstall: $(TARG:.1=.uninstall) $(TARG:.3=.uninstall) manuninstall + +.PHONY: maninstall manuninstall + +MANLOOP = \ + set -ef; \ + for k in $(MANPAGES); do \ + set -- $$k; \ + real=$$1; shift; \ + for targ; do \ + _ $$real $(MAN)/man$${real\#\#*.}/$$targ; \ + done; \ + done +maninstall: + _() { echo LN $$1 $${2##*/}; ln -sf $$1 $$2; }; $(MANLOOP) +manuninstall: + _() { echo RM $${2##*/}; rm -f $$2; }; $(MANLOOP) printinstall: echo 'Install directories:' diff --git a/mk/so.mk b/mk/so.mk @@ -3,7 +3,7 @@ SO = $(SOPTARG).$(SOEXT) SONAME = $(TARG).$(SOEXT) OFILES_PIC = $(OBJ:=.o_pic) -all: $(HFILES) $(SO) +all: $(HFILES) $(SO) install: $(SOPTARG).install uninstall: $(SOPTARG).uninstall diff --git a/test/client.c b/test/client.c @@ -149,8 +149,8 @@ threadmain(int argc, char *argv[]) { arg2 *a; char *address; - USED(argc, argv); - address = "unix!/tmp/ns.kris.:0/wmii"; + USED(argc); + USED(argv); address = "tcp!localhost!6663"; path = "/n/local/var/log/messages"; diff --git a/util/compile b/util/compile @@ -14,10 +14,10 @@ echo CC $($bin/cleanname ${BASE}$outfile) [ -n "$noisycc" ] && echo $CC -o $outfile $CFLAGS $@ eval '$CC -o $outfile '"$CFLAGS"' $@ >$xtmp 2>&1' status=$? -[ $? -eq 0 ] || echo $CC -o $outfile $CFLAGS $@ >&2 +[ $status -eq 0 ] || echo $CC -o $outfile $CFLAGS $@ >&2 base=$(echo $BASE | sed 's/,/\\,/g') -re='\([^[:space:]/]*\..:[0-9]\)' +re='\([^[:space:]/][^[:space:]]*\..:[0-9]\)' undup() { # GCC is crap. awk ' @@ -59,7 +59,7 @@ 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' | + egrep -iv ': (error|note): .?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|warning:.*warn_unused_result' | 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}' | diff --git a/util/grepdoc b/util/grepdoc @@ -0,0 +1,123 @@ +#!/usr/bin/env perl +use warnings; +use strict; +use POSIX qw(strftime); +use Data::Dumper; + +sub subst(&$_) { + my ($fn, $re, $str) = @_; + $str =~ s{$re}{$fn->()}ge; + return $str; +} + +sub detab(_) { + my ($text) = @_; + 1 while $text =~ s/^(.*?)\t/$1 . " " x (8 - length($1) % 8)/me; + return $text; +} + +my @c = grep /\.c$/, @ARGV; +my @h = grep /\.h$/, @ARGV; + +my %protos; +open(my $stderr, '>&', \*STDERR); +open STDERR, '>', '/dev/null'; + +open my $fd, '-|', 'cproto', '-I./include', @c; +for(<$fd>) { + chomp; + s/\b_ixp//g; + if(m/(\w+)\(/) { + push @{$protos{$1}}, $_; + } +} +open STDERR, '>&', $stderr; + +@ARGV = @h; +$_ = join "", map detab, <>; + +while(m/^typedef\b.*?(\w+);/gm) { + push @{$protos{$1}}, $& unless $& =~ m{\Q/* Deprecated */}; +} +while(m/^(?:enum|struct)\s+(\w+).*?^\}/gsm) { + my $proto = \@{$protos{$1}}; + push @$proto, subst {"$1$2$1..."} qr[(^ +)(\Q/* Private members */\E\n).*(?=\n\})]sm, $& + unless $& =~ m{\Q/* Deprecated */}; +} + +@ARGV = @c; +$_ .= join "", map detab, <>; + +sub section($$) { + my ($sect, $text) = @_; + $text =~ s/^\s+|\s+$//g; + $text =~ s/[^:`]$/$&\n/; + print "= $sect =\n\n$text\n"; +} + +print "MANPAGES ="; +while(m{(?<=/\*\*\n)(?:[^*]|\*[^/])+}g) { + local $_ = $&; + chop; + + my @names; + my %section; + my $header = ''; + s/ \* ?//gm; + + s{^(\w+:.*?)\n\n}{ + $header = $1; + $header =~ s{^(?:Function|Type|Variable): (\w+)}{ + push @names, $1; + join("\n", @{$protos{$1} or [$1]}) . "\n" + }gem; + ""; + }se; + + unless(@names) { + print STDERR $_; + next; + } + + sub despace { + my ($space) = m/^(\s*)/; + s/^$space//gm; + $_ + } + + s{^((?:\w.+):\n(?:.|\n)*?)(?:\n\n|\Z)}{ + %section = (%section, '', map despace, split /\n?^(\w.+):\n/m, $1); + ""; + }gem; + + print " \\\n\t'", (join " ", map {"$_.3"} @names), "'"; + + open my $stdout, ">&", STDOUT; + open STDOUT, '>', "man/$names[0].man3"; + + print <<EOF; +@{[uc $names[0]]} +libixp Manual +@{[strftime "%Y %b", localtime]} + +\%!includeconf: header.t2t + +EOF + + section 'NAME', join ", ", @names; + + section 'SYNOPSIS', "```\n$header```"; + + section 'PARAMETERS', subst {": $2\n" . (' ' x length $1)} qr/^(\s*(.*):)/m, $section{Params} . "\n:" + if exists $section{Params}; + + section 'DESCRIPTION', $_; + section 'RETURN VALUE', $section{Returns} if exists $section{Returns}; + section 'BUGS', $section{Bugs} if exists $section{Bugs}; + section 'SEE ALSO', subst {"$1(3)"} qr/\b[FSTV]<(.*?)>/, $section{'See also'} + if exists $section{'See also'}; + open STDOUT, ">&", $stdout +} +print "\n"; + +# vim:se sts=4 sw=4 et tw=0: diff --git a/util/link b/util/link @@ -27,9 +27,9 @@ 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=$? -[ $? -eq 0 ] || $LD -o $outfile $ofiles $LDFLAGS $args >&2 +[ $status -eq 0 ] || $LD -o $outfile $ofiles $LDFLAGS $args >&2 -sed 's/.*: In function `[^:]*: *//' $xtmp | egrep . | +sed 's/.*: In function `[^:]*: *//' $xtmp | egrep . | egrep -v 'is almost always misused|is dangerous, better use|in statically linked applications requires at runtime' rm -f $xtmp