ref: fc67b2fbbcfdbb28721d0217f21ead09ab6c279f
parent: e246a76f85e93963124f0420f437719b6b2c825c
author: halfwit <michaelmisch1985@gmail.com>
date: Thu Oct 12 01:38:55 PDT 2023
Update structure, add in some of svcfs
--- a/README.md
+++ /dev/null
@@ -1,102 +1,0 @@
-# Registry
-
-This is an interpretation of the Inferno Registry, for Plan9-like systems
-
-## Configuration
-
-Update your ipnet in /lib/ndb/local
-```
-ipnet=mynetwork ip=192.168.1.0 ipmask=255.255.255.0
- ipgw=192.168.1.1
- dns=1.1.1.1
- auth=authy
- registry=authy <---
- fs=servy
- cpu=crunchy
-```
-
-This is used by ndb/registry to find your network regfs
-
-Add the following to your /cfg/$sysname/cpurc, where $sysname matches what you entered above.
-
-```
-# Assuming you add a "registry" port mapping
-aux/svcfs -m /mnt/services /adm/services
-aux/listen1 -t tcp!*!registry /bin/exportfs -r /mnt/services
-```
-## Pieces
-
-Below are the main parts. Basic setup only requires an ndb/registry instance and ndb/regquery
-
-### aux/svcfs
-
-Usage: `aux/svcfs [-r] [-m mtpt] servicesfile`
-
-`svcfs` will periodically check a service is still alive with a gradual backoff, capping off at hourly.
-`svcfs` manages the contents of a file, `/adm/services`, which it will read in on startup
-It serves up on `/mnt/services`, making a new directory creates a new service,
-The dir contains many of the following files:
- - addr
- - status (ok/down)
- - uptime
- - description
- - fd0/fd1 (?)
-
-Services may be read by anyone, but can only be modified by the creator or registry owner. Request must come from users in the same authdom.
-
-### ndb/registry
-
-Usage: `ndb/registry [-r] [-s srvname]`
-- `-r` do not parse /cfg/$sysname/registry
-- `-s` Alternate address for Registry server
-
-Registry connects to a `svcfs`, by default checking for an entry in your local ipnet=.
-It parses `/cfg/$sysname/registry`, an ndb-formatted list of local services.
-
-```
-## /cfg/mysystem/registry
-
-# Local-only service, this is not written to the svcfs
-service=myservice
- addr=tcp!myserver!19293
- description='My local-only service'
- local=true
-
-# Network-shared service, this is written to the svcfs
-service=mysharedservice
- addr=tcp!myserver!19294
- description='My shared service'
-```
-
-In addition to the above style of service tuples, we could also handle local pseudo-services:
-
-```
-service='!g'
- addr=local!/bin/gcli
- description='Search Google from the command line'
- local=true
-
-service=plumber
- addr=local!/srv/plumb
- description='Local plumber instance'
- local=true
-```
-
-The point of which is more for bookkeeping, populating menus in an automated way, etc
-
-### ndb/regquery
-Usage: `nbd/regquery [-m mtpt] [-a] [query]`
-
-Connects to `mtpt`, by default at `/mnt/registry` and issues a search for the given query. If no value is passed in, all entries will be returned.
-
-- `-a` returns all services that match query, regardless of whether they are live or not
-
-Searches are for partial matches, searching for `"speaker"` will return `"outside-speaker-front"` and `"living-room-speaker"`, for example.
-
-### ndb/regdebug
-Like regquery, but issues queries directly to the given svcfs
-
-## Future
-- The code!
-- Libraries for services to publish services
-- Integration into `cpurc`
--- a/dns.h
+++ /dev/null
@@ -1,568 +1,0 @@
-#define NS2MS(ns) ((ns) / 1000000L)
-#define S2MS(s) ((s) * 1000LL)
-
-#define timems() NS2MS(nsec())
-
-typedef struct Ndbtuple Ndbtuple;
-
-enum
-{
- /* RR types; see: http://www.iana.org/assignments/dns-parameters */
- Ta= 1,
- Tns= 2,
- Tmd= 3,
- Tmf= 4,
- Tcname= 5,
- Tsoa= 6,
- Tmb= 7,
- Tmg= 8,
- Tmr= 9,
- Tnull= 10,
- Twks= 11,
- Tptr= 12,
- Thinfo= 13,
- Tminfo= 14,
- Tmx= 15,
- Ttxt= 16,
- Trp= 17,
- Tafsdb= 18,
- Tx25= 19,
- Tisdn= 20,
- Trt= 21,
- Tnsap= 22,
- Tnsapptr= 23,
- Tsig= 24,
- Tkey= 25,
- Tpx= 26,
- Tgpos= 27,
- Taaaa= 28,
- Tloc= 29,
- Tnxt= 30,
- Teid= 31,
- Tnimloc= 32,
- Tsrv= 33,
- Tatma= 34,
- Tnaptr= 35,
- Tkx= 36,
- Tcert= 37,
- Ta6= 38,
- Tdname= 39,
- Tsink= 40,
- Topt= 41,
- Tapl= 42,
- Tds= 43,
- Tsshfp= 44,
- Tipseckey= 45,
- Trrsig= 46,
- Tnsec= 47,
- Tdnskey= 48,
-
- Tspf= 99,
- Tuinfo= 100,
- Tuid= 101,
- Tgid= 102,
- Tunspec= 103,
-
- /* query types (all RR types are also queries) */
- Ttkey= 249, /* transaction key */
- Ttsig= 250, /* transaction signature */
- Tixfr= 251, /* incremental zone transfer */
- Taxfr= 252, /* zone transfer */
- Tmailb= 253, /* { Tmb, Tmg, Tmr } */
- Tmaila= 254, /* obsolete */
- Tall= 255, /* all records */
-
- /* classes */
- Csym= 0, /* internal symbols */
- Cin= 1, /* internet */
- Ccs, /* CSNET (obsolete) */
- Cch, /* Chaos net */
- Chs, /* Hesiod (?) */
-
- /* class queries (all class types are also queries) */
- Call= 255, /* all classes */
-
- /* opcodes */
- Oquery= 0<<11, /* normal query */
- Oinverse= 1<<11, /* inverse query (retired) */
- Ostatus= 2<<11, /* status request */
- Onotify= 4<<11, /* notify slaves of updates */
- Oupdate= 5<<11,
- Omask= 0xf<<11, /* mask for opcode */
-
- /* response codes */
- Rok= 0,
- Rformat= 1, /* format error */
- Rserver= 2, /* server failure (e.g. no answer from something) */
- Rname= 3, /* bad name */
- Runimplimented= 4, /* unimplemented */
- Rrefused= 5, /* we don't like you */
- Ryxdomain= 6, /* name exists when it should not */
- Ryxrrset= 7, /* rr set exists when it should not */
- Rnxrrset= 8, /* rr set that should exist does not */
- Rnotauth= 9, /* not authoritative */
- Rnotzone= 10, /* name not in zone */
- Rbadvers= 16, /* bad opt version */
-/* Rbadsig= 16, */ /* also tsig signature failure */
- Rbadkey= 17, /* key not recognized */
- Rbadtime= 18, /* signature out of time window */
- Rbadmode= 19, /* bad tkey mode */
- Rbadname= 20, /* duplicate key name */
- Rbadalg= 21, /* algorithm not supported */
- Rmask= 0x1f, /* mask for response */
- Rtimeout= 1<<5, /* timeout sending (for internal use only) */
-
- /* bits in flag word (other than opcode and response) */
- Fresp= 1<<15, /* message is a response */
- Fauth= 1<<10, /* true if an authoritative response */
- Ftrunc= 1<<9, /* truncated message */
- Frecurse= 1<<8, /* request recursion */
- Fcanrec= 1<<7, /* server can recurse */
-
- Domlen= 256, /* max domain name length (with NULL) */
- Labellen= 64, /* max domain label length (with NULL) */
- Strlen= 256, /* max string length (with NULL) */
-
- /* time to live values (in seconds) */
- Min= 60,
- Hour= 60*Min, /* */
- Day= 24*Hour, /* Ta, Tmx */
- Week= 7*Day, /* Tsoa, Tns */
- Year= 52*Week,
- DEFTTL= Day,
-
- /* reserved time (can't be timed out earlier) */
- Reserved= 5*Min,
-
- /* packet sizes */
- Maxudp= 512, /* maximum bytes per udp message sent */
- Maxudpin= 2048, /* maximum bytes per udp message rcv'd */
-
- /* length of domain name hash table */
- HTLEN= 4*1024,
-
- Maxpath= 128, /* size of mntpt */
- Maxlcks= 10, /* max. query-type locks per domain name */
- Maxauth= 16, /* proto for auth */
- Maxremote= 256, /* For registry, if you're more popular than this... */
- Maxmdns= 255, /* Limits for mDNS messages */
- Maxdial= 271, /* port + trns + !! + host */
-
- RRmagic= 0xdeadbabe,
- DNmagic= 0xa110a110,
-
- /* parallelism: tune; was 32; allow lots */
- Maxactive= 250,
-
- /* tune; was 60*1000; keep it short */
- Maxreqtm= 8*1000, /* max. ms to process a request */
-
- Notauthoritative = 0,
- Authoritative,
-};
-
-typedef struct Area Area;
-typedef struct Block Block;
-typedef struct Cert Cert;
-typedef struct DN DN;
-typedef struct DNSmsg DNSmsg;
-typedef struct Key Key;
-typedef struct Null Null;
-typedef struct RR RR;
-typedef struct Request Request;
-typedef struct SOA SOA;
-typedef struct Server Server;
-typedef struct Svc Svc;
-typedef struct Sig Sig;
-typedef struct Srv Srv;
-typedef struct Txt Txt;
-
-/*
- * a structure to track a request and any slave process handling it
- */
-struct Request
-{
- int isslave; /* pid of slave */
- uvlong aborttime; /* time in ms at which we give up */
- jmp_buf mret; /* where master jumps to after starting a slave */
- int id;
- char *from; /* who asked us? */
- void *aux;
-};
-
-/*
- * a domain name
- */
-struct DN
-{
- DN *next; /* hash collision list */
- ulong magic;
- char *name; /* owner */
- RR *rr; /* resource records off this name */
- ulong referenced; /* time last referenced */
- ulong ordinal;
- ushort class; /* RR class */
- uchar respcode; /* response code */
- uchar mark; /* for mark and sweep */
-};
-
-/*
- * security info
- */
-struct Block
-{
- int dlen;
- uchar *data;
-};
-struct Key
-{
- int flags;
- int proto;
- int alg;
- Block;
-};
-struct Cert
-{
- int type;
- int tag;
- int alg;
- Block;
-};
-struct Sig
-{
- Cert;
- int labels;
- ulong ttl;
- ulong exp;
- ulong incep;
- DN *signer;
-};
-struct Null
-{
- Block;
-};
-
-/*
- * text strings
- */
-struct Txt
-{
- Txt *next;
- char *p;
-};
-
-/*
- * registry service
- */
-struct Svc
-{
- int id; /* for server tracking */
- Svc *next;
- char labl[Maxmdns]; /* Use mDNS limits */
- char host[Maxmdns]; /* host ip */
- char mtpt[Maxpath];
- char auth[Maxauth];
- char trns[16]; /* transport tcp/ssh/gopher/carrierpidgeon */
- char port[8]; /* 9fs, numerical, etc - switch to #? */
- uchar perm; /* flag: from db */
-};
-
-/*
- * an unpacked resource record
- */
-struct RR
-{
- RR *next;
- ulong magic;
- DN *owner; /* domain that owns this resource record */
- uintptr pc; /* for tracking memory allocation */
- ulong ttl; /* time to live to be passed on */
- ulong expire; /* time this entry expires locally */
- ulong marker; /* used locally when scanning rrlists */
- ushort type; /* RR type */
- ushort query; /* query type is in response to */
- uchar auth; /* flag: authoritative */
- uchar db; /* flag: from database */
- uchar cached; /* flag: rr in cache */
- uchar negative; /* flag: this is a cached negative response */
-
- union { /* discriminated by negative & type */
- DN *negsoaowner; /* soa for cached negative response */
- DN *host; /* hostname - soa, cname, mb, md, mf, mx, ns, srv */
- DN *cpu; /* cpu type - hinfo */
- DN *mb; /* mailbox - mg, minfo */
- DN *ip; /* ip address - a, aaaa */
- DN *rp; /* rp arg - rp */
- uintptr arg0; /* arg[01] are compared to find dups in dn.c */
- };
- union { /* discriminated by negative & type */
- int negrcode; /* response code for cached negative resp. */
- DN *rmb; /* responsible maibox - minfo, soa, rp */
- DN *ptr; /* pointer to domain name - ptr */
- DN *os; /* operating system - hinfo */
- ulong pref; /* preference value - mx */
- ulong local; /* ns served from local database - ns */
- ushort port; /* - srv */
- uintptr arg1; /* arg[01] are compared to find dups in dn.c */
- };
- union { /* discriminated by type */
- SOA *soa; /* soa timers - soa */
- Srv *srv;
- Key *key;
- Cert *cert;
- Sig *sig;
- Null *null;
- Txt *txt;
- };
-};
-
-/*
- * list of servers
- */
-struct Server
-{
- Server *next;
- char *name;
-};
-
-/*
- * timers for a start-of-authority record. all ulongs are in seconds.
- */
-struct SOA
-{
- ulong serial; /* zone serial # */
- ulong refresh; /* zone refresh interval */
- ulong retry; /* zone retry interval */
- ulong expire; /* time to expiration */
- ulong minttl; /* min. time to live for any entry */
-
- Server *slaves; /* slave servers */
-};
-
-/*
- * srv (service location) record (rfc2782):
- * _service._proto.name ttl class(IN) 'SRV' priority weight port target
- */
-struct Srv
-{
- ushort pri;
- ushort weight;
-};
-
-typedef struct Rrlist Rrlist;
-struct Rrlist
-{
- int count;
- RR *rrs;
-};
-
-/*
- * domain messages
- */
-struct DNSmsg
-{
- ushort id;
- int flags;
- int qdcount; /* questions */
- RR *qd;
- int ancount; /* answers */
- RR *an;
- int nscount; /* name servers */
- RR *ns;
- int arcount; /* hints */
- RR *ar;
-};
-
-/*
- * definition of local area for dblookup
- */
-struct Area
-{
- Area *next;
-
- int len; /* strlen(area->soarr->owner->name) */
- RR *soarr; /* soa defining this area */
- int neednotify;
- int needrefresh;
-};
-
-typedef struct Cfg Cfg;
-struct Cfg {
- int cachedb;
- int resolver;
- int justforw; /* flag: pure resolver, just forward queries */
- int serve; /* flag: serve udp queries */
- int inside;
- int straddle;
-};
-
-/* (udp) query stats */
-typedef struct {
- QLock;
- ulong slavehiwat; /* procs */
- ulong qrecvd9p; /* query counts */
- ulong qrecvdudp;
- ulong qsent;
- ulong qrecvd9prpc; /* packet count */
- ulong alarms;
- /* reply times by count */
- ulong under10ths[3*10+2]; /* under n*0.1 seconds, n is index */
- ulong tmout;
- ulong tmoutcname;
- ulong tmoutv6;
-
- ulong answinmem; /* answers in memory */
- ulong negans; /* negative answers received */
- ulong negserver; /* neg ans with Rserver set */
- ulong negbaddeleg; /* neg ans with bad delegations */
- ulong negbdnoans; /* ⋯ and no answers */
- ulong negnorname; /* neg ans with no Rname set */
- ulong negcached; /* neg ans cached */
-} Stats;
-
-Stats stats;
-
-enum
-{
- Recurse,
- Dontrecurse,
- NOneg,
- OKneg,
-};
-
-extern Cfg cfg;
-extern char *dbfile;
-extern int debug;
-extern Area *delegated;
-extern char *logfile;
-extern int maxage; /* age of oldest entry in cache (secs) */
-extern char mntpt[];
-extern int needrefresh;
-extern int norecursion;
-extern ulong now; /* time base */
-extern vlong nowns;
-extern Area *owned;
-extern int sendnotifies;
-extern ulong target;
-extern char *trace;
-extern int traceactivity;
-extern char *zonerefreshprogram;
-extern Svc *registry;
-extern int rfd[Maxremote];
-
-#pragma varargck type "R" RR*
-#pragma varargck type "Q" RR*
-#pragma varargck type "G" Svc*
-#pragma varargck type "D" Svc*
-#pragma varargck type "N" Svc*
-
-/* dn.c */
-extern char *rrtname[];
-extern char *rname[];
-extern unsigned nrname;
-extern char *opname[];
-extern Lock dnlock;
-
-void abort(); /* char*, ... */;
-void addserver(Server**, char*);
-Server* copyserverlist(Server*);
-void db2cache(int);
-void dnage(DN*);
-void dnageall(int);
-void dnagedb(void);
-void dnagenever(DN *);
-void dnauthdb(void);
-void dndump(char*);
-void dninit(void);
-DN* dnlookup(char*, int, int);
-DN* idnlookup(char*, int, int);
-DN* ipalookup(uchar*, int, int);
-void dnptr(uchar*, uchar*, char*, int, int, int);
-void dnpurge(void);
-void dnslog(char*, ...);
-void dnstats(char *file);
-void* emalloc(int);
-char* estrdup(char*);
-void freeanswers(DNSmsg *mp);
-void freeserverlist(Server*);
-int getactivity(Request*, int);
-Area* inmyarea(char*);
-void putactivity(int);
-void reg2cache(void);
-void regconnect(void);
-char* rstr2cache(char*, int);
-Svc* rstr2svc(char*);
-char* rstrdtch(char*);
-char* rstrupdt(char*);
-RR* randomize(RR*);
-void reglog(char*, ...);
-RR* rralloc(int);
-void rrattach(RR*, int);
-int rravfmt(Fmt*);
-RR* rrcat(RR**, RR*);
-RR** rrcopy(RR*, RR**);
-int rrfmt(Fmt*);
-void rrfree(RR*);
-void rrfreelist(RR*);
-RR* rrlookup(DN*, int, int);
-char* rrname(int, char*, int);
-RR* rrremneg(RR**);
-RR* rrremtype(RR**, int);
-RR* rrremowner(RR**, DN*);
-RR* rrremfilter(RR**, int (*)(RR*, void*), void*);
-int rrsupported(int);
-int rrtype(char*);
-void slave(Request*);
-int subsume(char*, char*);
-int tsame(int, int);
-void unique(RR*);
-void warning(char*, ...);
-
-
-/* dnarea.c */
-void refresh_areas(Area*);
-void freearea(Area**);
-void addarea(DN *dp, RR *rp, Ndbtuple *t);
-
-/* dblookup.c */
-int baddelegation(RR*, RR*, uchar*);
-RR* dblookup(char*, int, int, int, int);
-RR* dnsservers(int);
-RR* domainlist(int);
-int insideaddr(char *dom);
-int insidens(uchar *ip);
-int myip(uchar *ip);
-int opendatabase(void);
-int outsidensip(int, uchar *ip);
-
-/* dns.c */
-char* walkup(char*);
-RR* getdnsservers(int);
-void logreply(int, uchar*, DNSmsg*);
-void logsend(int, int, uchar*, char*, char*, int);
-
-/* dnresolve.c */
-RR* dnresolve(char*, int, int, Request*, RR**, int, int, int, int*);
-int udpport(char *);
-int mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno);
-int seerootns(void);
-void initdnsmsg(DNSmsg *mp, RR *rp, int flags, ushort reqno);
-
-/* dnserver.c */
-void dnserver(DNSmsg*, DNSmsg*, Request*, uchar *, int);
-void dnudpserver(char*);
-
-/* dnnotify.c */
-void dnnotify(DNSmsg*, DNSmsg*, Request*);
-void notifyproc(void);
-
-/* reglookup.c */
-int openregistry(void);
-
-/* convDNS2M.c */
-int convDNS2M(DNSmsg*, uchar*, int);
-
-/* convM2DNS.c */
-char* convM2DNS(uchar*, int, DNSmsg*, int*);
-
-#pragma varargck argpos dnslog 1
--- a/lib/reglookup.c
+++ /dev/null
@@ -1,213 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <ndb.h>
-#include "dns.h"
-
-static Ndb *db;
-static QLock dblock;
-
-int
-openregistry(void)
-{
- if(db != nil)
- return 0;
-
- db = ndbopen(dbfile);
- return db!=nil ? 0: -1;
-}
-
-static void
-attach(Svc* svc, int persist)
-{
- svc->perm = !!persist;
-
- if(registry != nil){
- svc->next = registry;
- }
-
- svc->next = registry;
- registry = svc;
-}
-
-static char*
-detach(char *dial)
-{
- Svc *c, *last = 0;
- char buf[Maxdial]; /* trns is capped at 16, port 8 */
-
- for(c = registry; c; c = c->next){
- snprint(buf, Maxdial, "%s!%s!%s", c->trns, c->host, c->port);
- if(strcmp(buf, dial)==0){
- if(last == 0)
- registry = c->next;
- else
- last->next = c->next;
- free(c);
- return 0;
- }
- last = c;
- }
-
- return "found no matching service";
-}
-
-static void
-host2svc(Svc *svc, char *dial)
-{
- int n;
-
- /*
- * entry host=tcp!mything!9fs
- * for now, tokenize but we should allow short strings
- */
- n = strcspn(dial, "!");
- if(n < 1)
- strcpy(svc->trns, "tcp");
- else
- strecpy(svc->trns, svc->trns+n+1, dial);
- dial = dial + n + 1;
-
- n = strcspn(dial, "!");
- strecpy(svc->host, svc->host+n+1, dial);
-
- dial = dial + n + 1;
- if(sizeof(dial) < 1)
- strcpy(svc->port, "9fs");
- else if(sizeof(dial) > 8)
- /* If this starts happening, we should bump the number */
- strecpy(svc->port, svc->port + 8, dial);
- else
- strcpy(svc->port, dial);
-}
-
-static void
-dbtuple2cache(Ndbtuple *t, int persist)
-{
- Ndbtuple *et, *nt;
- Svc *svc;
-
-
- for(et = t; et; et = et->entry)
- if(strncmp(et->attr, "serv", 4)==0){
- svc = emalloc(sizeof(*svc));
- host2svc(svc, et->val);
- for(nt = et->entry; nt; nt = nt->entry)
- if(strcmp(nt->attr, "label")==0)
- strecpy(svc->labl, svc->labl+Maxmdns, nt->val);
- else if(strcmp(nt->attr, "auth")==0)
- strecpy(svc->auth, svc->auth+Maxauth, nt->val);
- else if(strcmp(nt->attr, "mtpt")==0)
- strecpy(svc->mtpt, svc->mtpt+Maxpath, nt->val);
- attach(svc, persist);
- };
-}
-
-static void
-dbfile2cache(Ndb *db)
-{
- Ndbtuple *t;
-
- if(debug)
- reglog("reading %s", db->file);
- Bseek(&db->b, 0, 0);
- while(t = ndbparse(db)){
- dbtuple2cache(t, 1);
- ndbfree(t);
- }
-
-
-}
-
-Svc*
-rstr2svc(char *entry)
-{
- Svc *svc;
- char *args[7];
-
- int i, n;
-
- n = tokenize(entry, args, 7);
-
- svc = emalloc(sizeof(*svc));
- host2svc(svc, estrdup(args[0]));
-
- for(i = 1; i < n - 1; i++)
- if(strcmp(args[i], "label")==0)
- strecpy(svc->labl, svc->labl+Maxmdns, args[++i]);
- else if(strcmp(args[i], "auth")==0)
- strecpy(svc->auth, svc->auth+Maxauth, args[++i]);
- else if(strcmp(args[i], "mtpt")==0)
- strecpy(svc->mtpt, svc->mtpt+Maxpath, args[++i]);
-
- return svc;
-}
-
-char*
-rstr2cache(char *entry, int persist)
-{
- Svc *svc;
-
- svc = rstr2svc(entry);
- attach(svc, persist);
- return 0;
-}
-
-char*
-rstrdtch(char *svc)
-{
- return detach(svc);
-}
-
-/* e.g. update tcp!foo!9fs label newlabel */
-char*
-rstrupdt(char *entry)
-{
- Svc *c, *svc = 0;
- char *args[7], buf[Maxdial];
- int i, n;
-
- n = tokenize(entry, args, 7);
-
- /* Find our service */
- for(c = registry; c; c = c->next){
- snprint(buf, Maxdial, "%s!%s!%s", c->trns, c->host, c->port);
- if(strcmp(buf, args[0])==0){
- svc = c;
- break;
- }
- }
-
- if(svc == 0)
- return "found no matching service";
-
- for(i = 1; i < n - 1; i++)
- if(strcmp(args[i], "label")==0)
- strecpy(svc->labl, svc->labl+Maxmdns, args[++i]);
- else if(strcmp(args[i], "auth")==0)
- strecpy(svc->auth, svc->auth+Maxauth, args[++i]);
- else if(strcmp(args[i], "mtpt")==0)
- strecpy(svc->mtpt, svc->mtpt+Maxpath, args[++i]);
-
- return 0;
-}
-
-void
-reg2cache(void)
-{
- Ndb *ndb;
-
- qlock(&dblock);
- if(openregistry() < 0){
- qunlock(&dblock);
- return;
- }
-
- if(debug)
- syslog(0, logfile, "building cache from db");
-
- for(ndb = db; ndb; ndb = ndb->next)
- dbfile2cache(ndb);
-
- qunlock(&dblock);
-}
--- a/mkfile
+++ /dev/null
@@ -1,16 +1,0 @@
-# registry mkfile
-</$objtype/mkfile
-
-TARG = \
- registry\
- regquery\
-
-HFILES = dns.h /$objtype/lib/libndb.a
-
-BIN=/$objtype/bin/ndb
-
-</sys/src/cmd/mkmany
-
-$O.registry: registry.$O reglookup.$O
- $LD -o $target $prereq
-
--- a/ndb/registry.c
+++ /dev/null
@@ -1,967 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include <bio.h>
-#include <ip.h>
-#include "dns.h"
-
-enum
-{
- Maxrequest= 1024,
- Maxreply= 8192,
- Maxrecords= 192,
- Maxfdata= 8192,
-
- Qdir= 0,
- Qreg= 1,
-};
-
-typedef struct Mfile Mfile;
-typedef struct Job Job;
-typedef struct Records Records;
-
-struct Mfile
-{
- Mfile *next;
-
- char *user;
- Qid qid;
- int fid;
- int bare;
-
- char reply[Maxreply];
- ushort rr[Maxrecords]; /* offset of record */
- ushort nrr; /* number of records */
-};
-
-/*
- * active requests
- */
-struct Job
-{
- Job *next;
- int flushed;
- Fcall request;
- Fcall reply;
-};
-Lock joblock;
-Job *joblist;
-
-struct {
- Lock;
- Mfile *inuse; /* active mfile's */
-} mfalloc;
-
-Svc *registry;
-int vers;
-int debug;
-char *dbfile = "/lib/ndb/registry";
-char *reguser;
-char mtpt[Maxpath];
-int rfd[Maxremote];
-int mfd[2];
-char *logfile = "registry";
-
-void rversion(Job*);
-void rflush(Job*);
-void rattach(Job*, Mfile*);
-char* rwalk(Job*, Mfile*);
-void ropen(Job*, Mfile*);
-void rcreate(Job*, Mfile*);
-void rread(Job*, Mfile*);
-void rwrite(Job*, Mfile*);
-void rclunk(Job*, Mfile*);
-void rremove(Job*, Mfile*);
-void rstat(Job*, Mfile*);
-void rwstat(Job*, Mfile*);
-void rauth(Job*);
-void mountinit(char*, char*);
-void setext(char*, int, char*);
-void io(void);
-
-static char* resolve(char*, ...);
-static char* addsvc(char*);
-static char* rmsvc(char*);
-static char* updatesvc(char*);
-static void refresh(void);
-static void regdump(char*);
-static void sendmsg(Job*, char*);
-
-static int scanfmt(Fmt*);
-static int srvfmt(Fmt*);
-static int dumpfmt(Fmt*);
-
-static char* query(Job*, Mfile*, char*, int);
-static char* resolvequery(Job*, Mfile*, char*, int);
-
-void
-usage(void)
-{
- fprint(2, "usage: %s [-xrd] [-f ndb-file]\n", argv0);
- exits("usage");
-}
-
-void
-main(int argc, char* argv[])
-{
- char servefile[Maxpath], ext[Maxpath];
- Dir *dir;
- ext[0] = 0;
-
- setnetmtpt(mtpt, sizeof mtpt, nil);
-
- ARGBEGIN{
- case 'd':
- debug = 1;
- break;
- case 'f':
- dbfile = EARGF(usage());
- break;
- case 'x':
- setnetmtpt(mtpt, sizeof mtpt, EARGF(usage()));
- setext(ext, sizeof ext, mtpt);
- break;
- } ARGEND;
- if(argc != 0)
- usage();
-
-
-
- rfork(RFREND|RFNOTEG);
-
- fmtinstall('F', fcallfmt);
- fmtinstall('G', srvfmt);
- fmtinstall('N', scanfmt);
- fmtinstall('D', dumpfmt);
-
- reglog("starting registry on %s", mtpt);
-
- if(openregistry())
- sysfatal("unable to open db file");
-
- reguser = estrdup(getuser());
- seprint(servefile, servefile+Maxpath, "#s/registry%s", ext);
-
- dir = dirstat(servefile);
- if (dir)
- sysfatal("%s exists; another registry instance is running", servefile);
- free(dir);
-
- mountinit(servefile, mtpt);
- reg2cache();
- io();
-
- _exits(0);
-}
-
-void
-setext(char *ext, int n, char *p)
-{
- int i, c;
-
- n--;
- for(i = 0; i < n; i++){
- c = p[i];
- if(c == 0)
- break;
- if(c == '/')
- c = '_';
- ext[i] = c;
- }
- ext[i] = 0;
-}
-
-void
-mountinit(char *service, char *mtpt)
-{
- int f;
- int p[2];
- char buf[32];
-
- if(pipe(p) < 0)
- sysfatal("pipe failed: %r");
-
- /*
- * make a /srv/registry
- */
- if((f = create(service, OWRITE|ORCLOSE, 0666)) < 0)
- sysfatal("create %s failed: %r", service);
- snprint(buf, sizeof buf, "%d", p[1]);
- if(write(f, buf, strlen(buf)) != strlen(buf))
- sysfatal("write %s failed: %r", service);
-
- /* copy namespace to avoid a deadlock */
- switch(rfork(RFFDG|RFPROC|RFNAMEG)){
- case 0: /* child: start main proc */
- close(p[1]);
- procsetname("%s", mtpt);
- break;
- case -1:
- sysfatal("fork failed: %r");
- default: /* parent: make /srv/registry, mount it, exit */
- close(p[0]);
-
- /*
- * put ourselves into the file system
- */
- if(mount(p[1], -1, mtpt, MAFTER, "") < 0)
- fprint(2, "registry mount failed: %r\n");
- _exits(0);
- }
- mfd[0] = mfd[1] = p[0];
-}
-
-Mfile*
-newfid(int fid, int needunused)
-{
- Mfile *mf;
-
- lock(&mfalloc);
- for(mf = mfalloc.inuse; mf != nil; mf = mf->next)
- if(mf->fid == fid){
- unlock(&mfalloc);
- if(needunused)
- return nil;
- return mf;
- }
- mf = emalloc(sizeof(*mf));
- mf->fid = fid;
- mf->qid.vers = vers;
- mf->qid.type = QTDIR;
- mf->qid.path = 0LL;
- mf->user = estrdup(reguser);
- mf->next = mfalloc.inuse;
- mfalloc.inuse = mf;
- mf->bare = 1;
- unlock(&mfalloc);
- return mf;
-}
-
-void
-freefid(Mfile *mf)
-{
- Mfile **l;
-
- lock(&mfalloc);
- for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next)
- if(*l == mf){
- *l = mf->next;
- free(mf->user);
- memset(mf, 0, sizeof *mf); /* cause trouble */
- free(mf);
- unlock(&mfalloc);
- return;
- }
- unlock(&mfalloc);
- sysfatal("freeing unused fid");
-}
-
-Mfile*
-copyfid(Mfile *mf, int fid)
-{
- Mfile *nmf;
-
- nmf = newfid(fid, 1);
- if(nmf == nil)
- return nil;
- nmf->fid = fid;
- free(nmf->user);
- nmf->user = estrdup(mf->user);
- nmf->qid.type = mf->qid.type;
- nmf->qid.path = mf->qid.path;
- nmf->qid.vers = vers++;
- return nmf;
-}
-
-Job*
-newjob(void)
-{
- Job *job;
-
- job = emalloc(sizeof *job);
- lock(&joblock);
- job->next = joblist;
- joblist = job;
- job->request.tag = -1;
- unlock(&joblock);
- return job;
-}
-
-void
-freejob(Job *job)
-{
- Job **l;
-
- lock(&joblock);
- for(l = &joblist; *l; l = &(*l)->next)
- if(*l == job){
- *l = job->next;
- memset(job, 0, sizeof *job); /* cause trouble */
- free(job);
- break;
- }
- unlock(&joblock);
-}
-
-void
-flushjob(int tag)
-{
- Job *job;
-
- lock(&joblock);
- for(job = joblist; job; job = job->next)
- if(job->request.tag == tag && job->request.type != Tflush){
- job->flushed = 1;
- break;
- }
- unlock(&joblock);
-}
-
-void
-io(void)
-{
- long n;
- Mfile *mf;
- uchar mdata[IOHDRSZ + Maxfdata];
- Job *job;
-
- while((n = read9pmsg(mfd[0], mdata, sizeof mdata)) != 0){
- if(n < 0){
- syslog(1, logfile, "error reading 9P from %s: %r", mtpt);
- break;
- }
-
- job = newjob();
- if(convM2S(mdata, n, &job->request) != n){
- reglog("format error %ux %ux %ux %ux %ux",
- mdata[0], mdata[1], mdata[2], mdata[3], mdata[4]);
- freejob(job);
- break;
- }
- mf = newfid(job->request.fid, 0);
- if(debug)
- reglog("%F", &job->request);
-
- switch(job->request.type){
- default:
- warning("unknown request type %d", job->request.type);
- break;
- case Tversion:
- rversion(job);
- break;
- case Tauth:
- rauth(job);
- break;
- case Tflush:
- rflush(job);
- break;
- case Tattach:
- rattach(job, mf);
- break;
- case Twalk:
- rwalk(job, mf);
- break;
- case Topen:
- ropen(job, mf);
- break;
- case Tcreate:
- rcreate(job, mf);
- break;
- case Tread:
- rread(job, mf);
- break;
- case Twrite:
- rwrite(job, mf);
- break;
- case Tclunk:
- rclunk(job, mf);
- break;
- case Tremove:
- rremove(job, mf);
- break;
- case Tstat:
- rstat(job, mf);
- break;
- case Twstat:
- rwstat(job, mf);
- break;
- }
-
- freejob(job);
- }
-}
-
-void
-rversion(Job *job)
-{
- if(job->request.msize > IOHDRSZ + Maxfdata)
- job->reply.msize = IOHDRSZ + Maxfdata;
- else
- job->reply.msize = job->request.msize;
- job->reply.version = "9P2000";
- if(strncmp(job->request.version, "9P", 2) != 0)
- job->reply.version = "unknown";
- sendmsg(job, nil);
-}
-
-void
-rauth(Job *job)
-{
- sendmsg(job, "registry: authentication not required");
-}
-
-void
-rflush(Job *job)
-{
- flushjob(job->request.oldtag);
- sendmsg(job, 0);
-}
-
-void
-rattach(Job *job, Mfile *mf)
-{
- if(mf->user != nil)
- free(mf->user);
- mf->user = estrdup(job->request.uname);
- mf->qid.vers = vers++;
- mf->qid.type = QTDIR;
- mf->qid.path = 0LL;
- job->reply.qid = mf->qid;
- sendmsg(job, 0);
-}
-
-char*
-rwalk(Job *job, Mfile *mf)
-{
- int i, nelems;
- char *err;
- char **elems;
- Mfile *nmf;
- Qid qid;
-
- err = 0;
- nmf = nil;
- elems = job->request.wname;
- nelems = job->request.nwname;
- job->reply.nwqid = 0;
-
- if(job->request.newfid != job->request.fid){
- /* clone fid */
- nmf = copyfid(mf, job->request.newfid);
- if(nmf == nil){
- err = "clone bad newfid";
- goto send;
- }
- mf = nmf;
- }
- /* else nmf will be nil */
-
- qid = mf->qid;
- if(nelems > 0){
- /* walk fid */
- for(i=0; i<nelems && i<MAXWELEM; i++){
- if((qid.type & QTDIR) == 0){
- err = "not a directory";
- break;
- }
- if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){
- qid.type = QTDIR;
- qid.path = Qdir;
- Found:
- job->reply.wqid[i] = qid;
- job->reply.nwqid++;
- continue;
- }
- if(strcmp(elems[i], "registry") == 0){
- qid.type = QTFILE;
- qid.path = Qreg;
- goto Found;
- }
- err = "file does not exist";
- break;
- }
- }
-
- send:
- if(nmf != nil && (err!=nil || job->reply.nwqid<nelems))
- freefid(nmf);
- if(err == nil)
- mf->qid = qid;
- sendmsg(job, err);
- return err;
-}
-
-void
-ropen(Job *job, Mfile *mf)
-{
- int mode;
- char *err;
-
- err = 0;
- mode = job->request.mode;
- if(mf->qid.type & QTDIR)
- if(mode)
- err = "permission denied";
- job->reply.qid = mf->qid;
- job->reply.iounit = 0;
- sendmsg(job, err);
-}
-
-void
-rcreate(Job *job, Mfile *mf)
-{
- USED(mf);
- sendmsg(job, "creation permission denied");
-}
-
-void rclunk(Job *job, Mfile *mf)
-{
- freefid(mf);
- sendmsg(job, 0);
-}
-
-void
-rremove(Job *job, Mfile *mf)
-{
- USED(mf);
- sendmsg(job, "remove permission denied");
-}
-
-void
-rread(Job *job, Mfile *mf)
-{
- int i, n;
- long clock;
- ulong cnt;
- vlong off;
- char *err;
- uchar buf[Maxfdata];
- Dir dir;
-
- n = 0;
- err = nil;
- off = job->request.offset;
- cnt = job->request.count;
- *buf = '\0';
- job->reply.data = (char*)buf;
- if(mf->qid.type & QTDIR){
- clock = time(nil);
- if(off == 0){
- memset(&dir, 0, sizeof dir);
- dir.name = "registry";
- dir.qid.type = QTFILE;
- dir.qid.vers = vers;
- dir.qid.path = Qreg;
- dir.mode = 0666;
- dir.length = 0;
- dir.uid = dir.gid = dir.muid = mf->user;
- dir.atime = dir.mtime = clock;
- n = convD2M(&dir, buf, sizeof buf);
- }
- } else if (off < 0)
- err = "negative read offset";
- else {
- if(mf->bare)
- query(job, mf, "all", 0);
- for(i = 1; i < mf->nrr; i++)
- if(mf->rr[i] > off)
- break;
- if(i <= mf->nrr){
- if(off + cnt > mf->rr[i])
- n = mf->rr[i] - off;
- else
- n = cnt;
- assert(n >= 0);
- job->reply.data = mf->reply + off;
- }
- }
- job->reply.count = n;
- sendmsg(job, err);
-}
-
-void
-rwrite(Job *job, Mfile *mf)
-{
- int send, pipe2rc;
- ulong cnt;
- char *err, *atype;
- char errbuf[ERRMAX];
-
- err = nil;
- cnt = job->request.count;
- send = 1;
- if(mf->qid.type & QTDIR)
- err = "can't write directory";
- else if (job->request.offset != 0)
- err = "writing at non-zero offset";
- else if (cnt >= Maxrequest)
- err = "request too long";
- else
- send = 0;
- if(send)
- goto send;
-
- job->request.data[cnt] = 0;
- if(cnt > 0 && job->request.data[cnt-1] == '\n')
- job->request.data[cnt-1] = 0;
-
- if(strcmp(mf->user, "none") == 0 || strcmp(mf->user, reguser) != 0)
- goto query; /* We don't want remote clients to modify our local */
-
- /*
- * special commands
- */
- send = 1;
- if(strcmp(job->request.data, "debug")==0)
- debug ^= 1;
- else if(strcmp(job->request.data, "dump")==0)
- regdump("/lib/ndb/regdump");
- else if (strcmp(job->request.data, "refresh")==0)
- refresh();
- else if (strncmp(job->request.data, "add ", 4)==0)
- err = addsvc(job->request.data + 4);
- else if (strncmp(job->request.data, "rm ", 3)==0)
- err = rmsvc(job->request.data + 3);
- else if (strncmp(job->request.data, "update ", 7)==0)
- err = updatesvc(job->request.data + 7);
- else
- send = 0;
- if (send)
- goto send;
-
-query:
- /*
- * kill previous reply
- */
- mf->nrr = 0;
- mf->rr[0] = 0;
- pipe2rc = 0;
-
- atype = strchr(job->request.data, ' ');
- if(atype == 0){
- snprint(errbuf, sizeof errbuf, "illegal request %s", job->request.data);
- err = errbuf;
- goto send;
- } else
- *atype++ = 0;
-
- if(strcmp(atype, "svc") == 0)
- pipe2rc++;
- else if(strcmp(atype, "scan") != 0){
- snprint(errbuf, sizeof errbuf, "unknown query %s", atype);
- err = errbuf;
- goto send;
- }
-
- err = query(job, mf,job->request.data, pipe2rc);
-send:
- mf->bare = 0;
- job->reply.count = cnt;
- sendmsg(job, err);
-}
-
-void
-rstat(Job *job, Mfile *mf)
-{
- Dir dir;
- uchar buf[IOHDRSZ+Maxfdata];
-
- memset(&dir, 0, sizeof dir);
- if(mf->qid.type & QTDIR){
- dir.name = ".";
- dir.mode = DMDIR|0555;
- }else{
- dir.name = "registry";
- dir.mode = 0666;
- }
- dir.qid = mf->qid;
- dir.length = 0;
- dir.uid = dir.gid = dir.muid = mf->user;
- dir.atime = dir.mtime = time(nil);
- job->reply.nstat = convD2M(&dir, buf, sizeof buf);
- job->reply.stat = buf;
- sendmsg(job, 0);
-}
-
-void
-rwstat(Job *job, Mfile *mf)
-{
- USED(mf);
- sendmsg(job, "wstat permission denied");
-}
-
-static char *
-resolvequery(Job *job, Mfile *mf, char *p, int pipe2rc)
-{
- int match, i;
- int n;
- Svc *c;
-
- char cmd[256];
- char buf[8192+1];
-
- lock(&joblock);
- if(!job->flushed){
- match = n = 0;
- mf->nrr = 0;
-
- snprint(cmd, sizeof(cmd), "%s %s", p, ((pipe2rc)?"svc":"scan"));
-
- for(i = 0; i < Maxremote && !match && rfd[i] > 1; i++){
- seek(rfd[i], 0, 0);
- write(rfd[i], cmd, sizeof cmd);
-
- seek(rfd[i], 0, 0);
- while(read(rfd[i], buf, sizeof(buf)-1) > 0){
- match = 1;
- c = rstr2svc(buf);
- mf->rr[mf->nrr++] = n;
- if(pipe2rc)
- n += snprint(mf->reply+n, Maxreply-n, "%G", c);
- else
- n += snprint(mf->reply+n, Maxreply-n, "%N", c);
- free(c);
- }
- }
- }
- unlock(&joblock);
-
- return 0;
-}
-
-static char *
-query(Job *job, Mfile *mf, char *p, int pipe2rc)
-{
- int n;
-
- Svc *c;
- lock(&joblock);
- if(!job->flushed){
- n = 0;
- mf->nrr = 0;
- for(c = registry; c && n < Maxreply; c = c->next)
- if((strncmp(p, c->labl, strlen(p))==0) || (strcmp(p, "all")==0)){
- mf->rr[mf->nrr++] = n;
- if(pipe2rc)
- n += snprint(mf->reply+n, Maxreply-n, "%G", c);
- else
- n += snprint(mf->reply+n, Maxreply-n, "%N", c);
- }
- mf->rr[mf->nrr] = n;
- }
- unlock(&joblock);
- return nil;
-}
-
-static void
-sendmsg(Job *job, char *err)
-{
- int n;
- uchar mdata[IOHDRSZ+Maxfdata];
- char ename[ERRMAX];
-
- if(err){
- job->reply.type = Rerror;
- snprint(ename, sizeof ename, "registry: %s", err);
- job->reply.ename = ename;
- }else
- job->reply.type = job->request.type+1;
- job->reply.tag = job->request.tag;
- n = convS2M(&job->reply, mdata, sizeof mdata);
- if(n == 0){
- warning("sendmsg convS2M of %F returns 0", &job->reply);
- abort();
- }
- lock(&joblock);
- if(job->flushed == 0)
- if(write(mfd[1], mdata, n)!=n)
- sysfatal("mount write");
- unlock(&joblock);
- if(debug)
- reglog("%F %d", &job->reply, n);
-}
-
-static void
-regdump(char *file)
-{
- Svc *rp;
- int fd;
-
- fd = create(file, OWRITE, 0666);
- if(fd < 0)
- return;
- lock(&mfalloc);
- for(rp = registry; rp; rp = rp->next)
- fprint(fd, "%D\n\n", rp);
- unlock(&mfalloc);
- close(fd);
-}
-
-static void
-refresh(void)
-{
- Svc *c;
- char dial[Maxdial];
-
- for(c = registry; c; c = c->next){
- /* Don't remove the ones we've added since startup */
- if(!c->perm)
- continue;
- snprint(dial, Maxdial, "%s!%s!%s", c->trns, c->host, c->port);
- rmsvc(dial);
- /* Reset so we don't have messy loops */
- c = registry;
- }
- reg2cache();
-}
-
-static char *
-resolve(char *cmd, ...)
-{
- int n;
- char fullcmd[256];
- char buf[8192+1];
- va_list arg;
-
- va_start(arg, cmd);
- vseprint(fullcmd, fullcmd+sizeof(fullcmd), cmd, arg);
- va_end(arg);
-
- /* We only operate on our local rfd */
- seek(rfd[0], 0, 0);
- write(rfd[0], fullcmd, sizeof fullcmd);
-
- seek(rfd[0], 0, 0);
- while((n = read(rfd[0], buf, sizeof(buf)-1)) > 0){
- buf[n++] = '\n';
- write(1, buf, n);
- }
- return buf;
-}
-
-static char *
-addsvc(char *args)
-{
- if(debug)
- reglog("Adding entry: %s", args);
-
- return rstr2cache(args, 0);
-}
-
-static char *
-rmsvc(char *args)
-{
- if(debug)
- reglog("Removing entry: %s", args);
- return rstrdtch(args);
-}
-
-static char *
-updatesvc(char *args)
-{
- if(debug)
- reglog("Updating entry: %s", args);
- return rstrupdt(args);
-}
-
-void
-warning(char *fmt, ...)
-{
- char regerr[256];
- va_list arg;
-
- va_start(arg, fmt);
- vseprint(regerr, regerr+sizeof(regerr), fmt, arg);
- va_end(arg);
- syslog(1, logfile, regerr);
-}
-
-void
-reglog(char *fmt, ...)
-{
- char regerr[256];
- va_list arg;
-
- va_start(arg, fmt);
- vseprint(regerr, regerr+sizeof(regerr), fmt, arg);
- va_end(arg);
- syslog(0, logfile, regerr);
-}
-
-void*
-emalloc(int size)
-{
- void *x;
-
- x = malloc(size);
- if(x == nil)
- sysfatal("out of memory");
- memset(x, 0, size);
- return x;
-}
-
-char*
-estrdup(char *s)
-{
- int size;
- char *p;
-
- size = strlen(s);
- p = malloc(size+1);
- if(p == nil)
- sysfatal("out of memory");
- memmove(p, s, size);
- p[size] = 0;
- return p;
-}
-
-static int
-srvfmt(Fmt *f)
-{
- Svc *r;
- char mf[Maxpath+1], auth[7];
-
- r = va_arg(f->args, Svc*);
- mf[0] = 0;
- auth[0] = 0;
-
- if(strcmp(r->mtpt, "")!= 0)
- snprint(mf, sizeof(r->mtpt)+1, " %s", r->mtpt);
-
- if(strcmp(r->auth, "none")==0)
- snprint(auth, 4, "srv");
- else
- snprint(auth, 7, "srvtls");
-
- return fmtprint(f, "%s!%s!%s\n",
- r->trns, r->host, r->port);
-}
-
-static int
-scanfmt(Fmt *f)
-{
- Svc *r;
- char mf[Maxpath+6]; /* pad for our tuple attrs */
-
- mf[0] = 0;
- r = va_arg(f->args, Svc*);
- if(strcmp(r->mtpt, "")!=0)
- snprint(mf, sizeof(r->mtpt)+6, " mtpt=%s", r->mtpt);
- return fmtprint(f, "service=%s!%s!%s label='%s' auth=%s%s\n",
- r->trns, r->host, r->port, r->labl, r->auth, mf);
-}
-
-static int
-dumpfmt(Fmt *f)
-{
- Svc *r;
- char mf[Maxpath+7]; /* pad for our tuple attrs */
-
- r = va_arg(f->args, Svc*);
- if(r->mtpt != 0)
- snprint(mf, sizeof(r->mtpt) + 7, "\n\tmtpt=%s", r->mtpt);
- return fmtprint(f, "service=%s!%s!%s\n\tlabel=%s\n\tauth=%s%s",
- r->trns, r->host, r->port, r->labl, r->auth, mf);
-}
-
--- a/ndb/regquery.c
+++ /dev/null
@@ -1,67 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <ctype.h>
-#include <ndb.h>
-#include "dns.h"
-#include "ip.h"
-
-void
-usage(void)
-{
- fprint(2, "usage: regquery [-s] [-f registry] query\n");
- exits("usage");
-}
-
-static void
-queryregistry(int fd, char *line, int n)
-{
- char buf[8192+1];
-
- seek(fd, 0, 0);
- write(fd, line, n);
-
- seek(fd, 0, 0);
- while((n = read(fd, buf, sizeof(buf)-1)) > 0)
- write(1, buf, n);
-}
-
-static void
-query(int fd, char *q, int pipe2rc)
-{
- char arg[260];
-
- if(strlen(q) > 255)
- sysfatal("query too long");
-
- sprint(arg, "%s %s", q, (pipe2rc) ? "svc":"scan");
- queryregistry(fd, arg, sizeof(arg));
-}
-
-void
-main(int argc, char *argv[])
-{
- int fd, pipe2rc = 0;
- char *rst = "/net/registry";
-
- ARGBEGIN {
- case 's':
- pipe2rc++;
- break;
- case 'f':
- rst = EARGF(usage());
- break;
- default:
- usage();
- } ARGEND;
-
- if(argc != 1)
- usage();
-
- fd = open(rst, ORDWR);
- if(fd < 0)
- sysfatal("can't open %s: %r", rst);
-
- query(fd, argv[0], pipe2rc);
- exits(0);
-}