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:
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