Uriel and I were talking about shipping rc-httpd with werc and writing
a script to serve a default example site from the base install. To that
end, I thought we could make use of listen1 from p9p. The patches
below may not be the ideal way to organize things in the tree, but
with these pieces it does build and run as expected.
-sl
diff -r e39eeddcc295 Makefile
--- a/Makefile Thu Jan 06 09:50:05 2011 +0000
+++ b/Makefile Mon Feb 21 22:43:02 2011 -0600
@@ -27,6 +27,7 @@
grep\
hoc\
join\
+ listen1\
look\
ls\
md5sum\
diff -r e39eeddcc295 lib9/auth.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib9/auth.h Mon Feb 21 22:43:02 2011 -0600
@@ -0,0 +1,169 @@
+#ifndef __AUTH_H__
+#define __AUTH_H__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+#pragma src "/sys/src/libauth"
+#pragma lib "libauth.a"
+*/
+AUTOLIB(auth)
+
+/*
+ * Interface for typical callers.
+ */
+
+typedef struct AuthInfo AuthInfo;
+typedef struct Chalstate Chalstate;
+typedef struct Chapreply Chapreply;
+typedef struct MSchapreply MSchapreply;
+typedef struct UserPasswd UserPasswd;
+typedef struct AuthRpc AuthRpc;
+
+struct CFid;
+
+enum
+{
+ MAXCHLEN= 256, /* max challenge length */
+ MAXNAMELEN= 256, /* maximum name length */
+ MD5LEN= 16,
+
+ ARok = 0, /* rpc return values */
+ ARdone,
+ ARerror,
+ ARneedkey,
+ ARbadkey,
+ ARwritenext,
+ ARtoosmall,
+ ARtoobig,
+ ARrpcfailure,
+ ARphase,
+
+ AuthRpcMax = 4096
+};
+
+struct AuthRpc
+{
+ int afd;
+ struct CFid *afid;
+ char ibuf[AuthRpcMax];
+ char obuf[AuthRpcMax];
+ char *arg;
+ uint narg;
+};
+
+struct AuthInfo
+{
+ char *cuid; /* caller id */
+ char *suid; /* server id */
+ char *cap; /* capability (only valid on server side) */
+ int nsecret; /* length of secret */
+ uchar *secret; /* secret */
+};
+
+struct Chalstate
+{
+ char *user;
+ char chal[MAXCHLEN];
+ int nchal;
+ void *resp;
+ int nresp;
+
+/* for implementation only */
+ AuthRpc *rpc; /* to factotum */
+ char userbuf[MAXNAMELEN]; /* temp space if needed */
+ int userinchal; /* user was sent to obtain challenge */
+};
+
+struct Chapreply /* for protocol "chap" */
+{
+ uchar id;
+ char resp[MD5LEN];
+};
+
+struct MSchapreply /* for protocol "mschap" */
+{
+ char LMresp[24]; /* Lan Manager response */
+ char NTresp[24]; /* NT response */
+};
+
+struct UserPasswd
+{
+ char *user;
+ char *passwd;
+};
+
+extern int newns(char*, char*);
+extern int addns(char*, char*);
+
+extern int noworld(char*);
+extern int amount(int, char*, int, char*);
+
+/* these two may get generalized away -rsc */
+extern int login(char*, char*, char*);
+extern int httpauth(char*, char*);
+
+typedef struct Attr Attr;
+enum {
+ AttrNameval, /* name=val -- when matching, must have
name=val */
+ AttrQuery, /* name? -- when matching, must be present */
+ AttrDefault /* name:=val -- when matching, if present must
match INTERNAL */
+};
+struct Attr
+{
+ int type;
+ Attr *next;
+ char *name;
+ char *val;
+};
+
+typedef int AuthGetkey(char*);
+
+int _attrfmt(Fmt*);
+Attr *_copyattr(Attr*);
+Attr *_delattr(Attr*, char*);
+Attr *_findattr(Attr*, char*);
+void _freeattr(Attr*);
+Attr *_mkattr(int, char*, char*, Attr*);
+Attr *_parseattr(char*);
+char *_strfindattr(Attr*, char*);
+/*
+#pragma varargck type "A" Attr*
+*/
+
+extern AuthInfo* fauth_proxy(int, AuthRpc *rpc, AuthGetkey *getkey, char
*params);
+extern AuthInfo* auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...);
+extern AuthInfo* fsfauth_proxy(struct CFid*, AuthRpc *rpc, AuthGetkey
*getkey, char *params);
+extern AuthInfo* fsauth_proxy(struct CFid*, AuthGetkey *getkey, char
*fmt, ...);
+extern int auth_getkey(char*);
+extern int (*amount_getkey)(char*);
+extern void auth_freeAI(AuthInfo *ai);
+extern int auth_chuid(AuthInfo *ai, char *ns);
+extern Chalstate *auth_challenge(char*, ...);
+extern AuthInfo* auth_response(Chalstate*);
+extern int auth_respond(void*, uint, char*, uint, void*, uint,
AuthGetkey *getkey, char*, ...);
+extern void auth_freechal(Chalstate*);
+extern AuthInfo* auth_userpasswd(char *user, char *passwd);
+extern UserPasswd* auth_getuserpasswd(AuthGetkey *getkey, char*, ...);
+extern AuthInfo* auth_getinfo(AuthRpc *rpc);
+extern AuthRpc* auth_allocrpc(void);
+extern Attr* auth_attr(AuthRpc *rpc);
+extern void auth_freerpc(AuthRpc *rpc);
+extern uint auth_rpc(AuthRpc *rpc, char *verb, void *a, int n);
+extern int auth_wep(char*, char*, ...);
+
+extern struct CFsys* fsamount(int fd, char *aname);
+extern struct CFsys* nsamount(char *name, char *aname);
+
+
+/*
+#pragma varargck argpos auth_proxy 3
+#pragma varargck argpos auth_challenge 1
+#pragma varargck argpos auth_respond 3
+#pragma varargck argpos auth_getuserpasswd 2
+*/
+#ifdef __cplusplus
+}
+#endif
+#endif
diff -r e39eeddcc295 listen1/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/listen1/Makefile Mon Feb 21 22:43:02 2011 -0600
@@ -0,0 +1,10 @@
+# listen1 - listen1 unix port from plan9
+# Depends on ../lib9
+
+TARG = listen1
+
+include ../std.mk
+
+pre-uninstall:
+
+post-install:
diff -r e39eeddcc295 listen1/listen1.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/listen1/listen1.c Mon Feb 21 22:43:02 2011 -0600
@@ -0,0 +1,105 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+
+int verbose;
+int trusted;
+
+void
+usage(void)
+{
+ fprint(2, "usage: listen1 [-v] address cmd args...\n");
+ exits("usage");
+}
+
+char*
+remoteaddr(char *dir)
+{
+ static char buf[128];
+ char *p;
+ int n, fd;
+
+ snprint(buf, sizeof buf, "%s/remote", dir);
+ fd = open(buf, OREAD);
+ if(fd < 0)
+ return "";
+ n = read(fd, buf, sizeof(buf));
+ close(fd);
+ if(n > 0){
+ buf[n] = 0;
+ p = strchr(buf, '!');
+ if(p)
+ *p = 0;
+ return buf;
+ }
+ return "";
+}
+
+void
+main(int argc, char **argv)
+{
+ char dir[40], ndir[40];
+ int ctl, nctl, fd;
+
+ ARGBEGIN{
+ default:
+ usage();
+ case 't':
+ trusted = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ }ARGEND
+
+ if(argc < 2)
+ usage();
+
+ if(!verbose){
+ close(1);
+ fd = open("/dev/null", OWRITE);
+ if(fd != 1){
+ dup(fd, 1);
+ close(fd);
+ }
+ }
+
+ print("listen started\n");
+ ctl = announce(argv[0], dir);
+ if(ctl < 0)
+ sysfatal("announce %s: %r", argv[0]);
+
+ for(;;){
+ nctl = listen(dir, ndir);
+ if(nctl < 0)
+ sysfatal("listen %s: %r", argv[0]);
+
+ switch(rfork(RFFDG|RFPROC|RFNOWAIT|RFNOTEG)){
+ case -1:
+ close(nctl);
+ continue;
+ case 0:
+ fd = accept(nctl, ndir);
+ if(fd < 0){
+ fprint(2, "accept %s: can't open %s/data: %r",
argv[0], ndir);
+ _exits(0);
+ }
+ print("incoming call for %s from %s in %s\n", argv[0],
remoteaddr(ndir), ndir);
+ close(ctl);
+ close(nctl);
+ /*putenv("net", ndir); */
+ /*sprint(data, "%s/data", ndir); */
+ /*bind(data, "/dev/cons", MREPL); */
+ dup(fd, 0);
+ dup(fd, 1);
+ dup(fd, 2);
+ close(fd);
+ exec(argv[1], argv+1);
+ fprint(2, "exec: %r");
+ exits(nil);
+ default:
+ close(nctl);
+ break;
+ }
+ }
+}