ref: 28666dfbc05cfec48d53fbe9b08553925ea984bb
parent: 91c1b89f14d987811dc33894b34577e5837a8382
author: 9ferno <gophone2015@gmail.com>
date: Wed Feb 16 06:34:49 EST 2022
fixed bugs in smudge, reveal and immediate
--- /dev/null
+++ b/forth/cat.f
@@ -1,0 +1,26 @@
+: ioerror ( n -- ) ." ioerror: " . cr ;
+
+: show ( read_count -- )
+ dup 0 < if ioerror then
+ pad swap ( 'pad read_count ) type ;
+
+: untileof ( fd -- fd )
+ begin
+ dup pad 1024 sysread ( fd read_count )
+ ?dup while show ( fd )
+ repeat ;
+
+: cat ( 'filename-counted-string -- )
+ count ( 'filename nfilename )
+ cstring0 r/o sysopen ( fd )
+ dup -1 > ( fd fd>=0? )
+ if ( fd ) untileof sysclose drop
+ else ." open error: " .
+ then ;
+
+: scat ( 'filename nfilename -- ) \ nfilename = length of filename
+ cstring0 r/o sysopen ( fd )
+ dup -1 > ( fd fd>=0? )
+ if ( fd ) untileof sysclose drop
+ else ." open error: " .
+ then ;
--- /dev/null
+++ b/forth/dhcpclient.f
@@ -1,0 +1,677 @@
+variable Controlfd
+variable Datafd
+struct Conf
+{
+ /* locally generated */
+ char *type;
+ char *dev;
+ char mpoint[32];
+ int cfd; /* ifc control channel */
+ int rfd; /* iproute control channel */
+ char *cputype;
+ uchar hwa[32]; /* hardware address */
+ int hwatype;
+ int hwalen;
+ uchar cid[32];
+ int cidlen;
+ char *baud;
+
+ /* learned info */
+ uchar gaddr[IPaddrlen];
+ uchar laddr[IPaddrlen];
+ uchar mask[IPaddrlen];
+ uchar raddr[IPaddrlen];
+ uchar dns[8*IPaddrlen];
+ uchar fs[2*IPaddrlen];
+ uchar auth[2*IPaddrlen];
+ uchar ntp[2*IPaddrlen];
+ int mtu;
+
+ /* dhcp specific */
+ int state; Phase
+ int fd;
+ ulong xid;
+ ulong starttime;
+ char sname[64];
+ char hostname[256];
+ char domainname[256];
+ char dnsdomain[256];
+ uchar server[IPaddrlen]; /* server IP address */
+ ulong offered; /* offered lease time */
+ ulong lease; /* lease time */
+ ulong resend; /* # of resends for current state */
+ ulong timeout; /* time to timeout - seconds */
+
+ /*
+ * IPv6
+ */
+
+ /* router-advertisement related */
+ uchar sendra;
+ uchar recvra;
+ uchar mflag;
+ uchar oflag;
+ int maxraint; /* rfc2461, p.39: 4sec ≤ maxraint ≤ 1800sec, def 600 */
+ int minraint; /* 3sec ≤ minraint ≤ 0.75*maxraint */
+ int linkmtu;
+ int routerlt; /* router life time */
+ int reachtime; /* 3,600,000 msec, default 0 */
+ int rxmitra; /* default 0 */
+ int ttl; /* default 0 (unspecified) */
+
+ /* prefix related */
+ uchar lladdr[IPaddrlen];
+ uchar v6pref[IPaddrlen];
+ int prefixlen;
+ uchar onlink; /* flag: address is `on-link' */
+ uchar autoflag; /* flag: autonomous */
+ ulong validlt; /* valid lifetime (seconds) */
+ ulong preflt; /* preferred lifetime (seconds) */
+};
+
+variable Message 127 vallot \ allot 128 bytes on the variable heap for Message
+
+a! \ ( a c -- a+1 ) swap 1+ dup >r ! r> ;
+ipnoaddr ( a -- a+4 ) \ stores 4 0's at a
+ 4 0 do 0 a! loop
+
+: addnulladdr
+ hex
+ " add " Message swap ( a am n ) cmove
+ Message 5 + ipnoaddr
+ 020 ( a space ) a! ( a+4+4+1 )
+ ipnoaddr ( a+4+4+1+4 )
+ Message 13 Controlfd @ write-file
+
+listen open
+ start openlisten
+ variable Data 127 vallot
+ variable Devdir 39 vallot
+ " /net/udp!*!68" Data swap cmov
+ announce Data Devdir
+ " headers" Controlfd @ write-file
+
+ sprint(data, "%s/data", devdir);
+ fd = open(data, ORDWR);
+ if(fd < 0)
+ sysfatal("open %s: %r", data);
+ close(cfd);
+ return fd;
+ forget openlisten
+
+52 constant UDPHDRSIZE
+
+vhere constant Bootp 100 vallot
+ variable Bootp 100 vallot
+: Header Bootp ;
+: Opcode Bootp 4 + ;
+: Hardware Bootp 5 + ;
+: Type Hardware ;
+: Hardware.type Hardware ;
+: Hardware.length Hardware 1+ ;
+: Hops Bootp 6 + ;
+: Xid Bootp 7 + ;
+: Seconds Bootp 9 + ;
+: Flags Bootp 11 + ;
+: Client.Ip.Address Bootp 13 + ;
+: Yield.Ip.Address Bootp 13 + ;
+: Server.Ip.Address Bootp 13 + ;
+: Gateway.Ip.Address Bootp 13 + ;
+: Client.Hardware.Address Bootp 14 + ;
+: Server.hostname Bootp 15 + ;
+: File Bootp 16 + ;
+: Magic Bootp 17 + ;
+: Data Bootp 18 + ;
+
+: send ( type -- )
+
+: bootreply ( a n -- )
+ dup 300 < if ." bootreply: short bootp packet" terminate then
+ over >Xid Xid 4 c= not if exit then
+ over >Op c@ dup BOOTREPLY != if ." bootreply: bad op" emit exit then drop
+ options
+
+: lease ( time -- ) dup 0= if MIN_LEASE then Lease !
+: serverid ( ipaddr -- ) TODO check address Server !
+
+: offer ( a n -- )
+ Phase @ SELECTING != if exit then
+ 2dup IP_ADDRESS_LEASE_TIME ( a n a n mtype ) search time@ ( a n time ) lease
+ 2dup SERVER_IDENTIFIER ( a n a n mtype ) search ipaddr@ ( a n ipaddr ) serverid
+ over >Your_ip_address addr@ v4>v6 Localaddress !
+ over >Server_name Sname 64 cmove ( TODO make this a counted string )
+ ." server " Server .ipaddr ." name " Sname 64 type cr
+ Lease @ Offered !
+ REQUESTING Phase !
+ REQUEST send
+
+: ack ( a n -- )
+ Phase @
+ dup REQUESTING != >r
+ dup RENEWING != >r
+ dup REBINDING != r> r> and and if exit then
+ 2dup IP_ADDRESS_LEASE_TIME ( a n a n mtype ) search time@ ( a n time ) lease
+ parse options
+
+: nak ( a n -- ) 2drop INIT Phase !
+
+: dhcpreply ( a n -- )
+ 2dup bootreply
+ 2dup DHCP_MESSAGE_TYPE ( a n a n mtype ) search ( a n amtype ) c@ ( a n mtype )
+ dup DHCPOFFER = if offer exit else
+ dup DHCPACK = if ack exit else
+ dup DHCPNAK = if nak exit else
+ then then then
+ ." dhcpreply: unknown type" emit 2drop
+
+: ask
+ Phase @
+ dup SELECTING = if 0 Offered ! DISCOVER send else
+ dup RENEWING = if REQUEST send else
+ ." correspond invalid phase" terminate
+ then then drop
+
+\ split the short to 2 bytes
+: split2 ( n -- low high )
+ hex dup ( n n )
+ 0F0 and 8 rshift >r
+ 0F and r>
+ decimal
+
+\ split the long to 4 bytes
+: split4 ( n -- c0 c1 c2 c3 )
+ hex dup ( n n )
+ 0F000 and 24 rshift >r
+ 0F00 and 16 rshift >r
+ 0F0 and 8 rshift >r
+ 0F and ( c0 )
+ r> ( c0 c1 ) r> r> ( c0 c1 c2 c3 )
+ decimal
+
+\ rename put* functions to hnput* functions
+: put ( low .. high a n -- a+n ) \ store n bytes at a in big endian, high goes first
+ dup 0 = if ." put with n 0" terminate then
+ 0 do dup ( low .. high a a ) >r c! r> 1+ ( low .. high-1 a+1 ) loop
+: put8 ( byte a -- a+1 ) 1 put ;
+: put16 ( short a -- a+2 ) >r split2 r> 2 put ;
+: put32 ( long a -- a+4 ) >r split4 r> 4 put ;
+: putn ( source a n -- a+n ) 2dup + >r \ (R a+n )
+ cmove r> ;
+
+\ put in host network order - big endian
+: arrange ( .. 'placer len code a -- )
+ put8 ( .. 'placer len a+1 ) \ put the code type
+ put8 ( .. 'placer a+2 ) \ put the length
+ swap execute \ let the placer do the rest
+
+: optionstring ( countedstring code a -- a+stringlength )
+ >r >r count ( stringaddress length ) ' putn over ( stringaddress length 'placer length ) \ (R a code )
+ r> r> arrange
+
+: get ( a n -- high .. low a+n ) \ get n bytes at a in big endian, high comes first
+ 0 do dup ( a a ) >r c@ r> 1+ ( high a+1 ) loop
+: get8 ( a -- byte a+1 ) 1 get ;
+: get16 ( a -- short a+2 ) 2 get >r join2 r> ;
+: get32 ( a -- long a+4 ) 4 get >r join4 r> ;
+
+: save8 ( destination a -- byte a+1 ) get drop swap ! ;
+: save16 ( destination a -- short a+2 ) get16 drop swap ! ;
+: save32 ( destination a -- ) get32 drop swap ! ;
+: saven ( destination a n -- a+n ) 2dup + >r \ (R a+n )
+ >r swap >r ( a destination n ) cmove ;
+: check ( receivedlength expectedlength -- )
+ 2dup != if ." check lengths do not match" emit emit then
+: extract ( destination len 'puller code a -- )
+ dup 1+ @ 5 pick check ( destination len 'puller code a -- )
+ nip swap >r swap r> execute
+: pull ( destination 'puller code a -- ) \ if a1 == 0, option with that code not found
+ >Limit @ swap ( code end begin )
+ 2dup = if ." pull at the end " emit emit emit terminate then
+ begin dup i c@ = if r> rdrop extract exit
+ else i 1+ c@ then
+ ( 'puller code skip ) +loop
+
+: place ( low .. high len type a -- a+1+len ) \ store the option at a
+ dup >r c! ( low .. high len ) \ (R a )
+ r@ 1+ ( low .. high len a ) over >r c! ( low .. high ) \ (R a len ) type and len stored at a
+ r> r> 2 + ( low .. high len a+2 ) swap ( low .. high a+2 len ) put
+
+\ put in host network order - big endian
+: hnput ( a n n -- a+n ) \ (G put in host network order )
+ dup 2 = if drop ( a n ) swap >r short r> ( low high a ) 2 put exit then
+ dup 4 = if drop ( a n ) swap >r long r> ( c0 c1 c2 c3 a ) 4 put exit then
+ ." unknown number of bytes" emit terminate
+
+12 constant OPTION.HOSTNAME
+50 constant OPTION.REQUESTED_IP_ADDRESS
+55 constant OPTION.PARAMETER_REQUEST_LIST
+60 constant OPTION.VENDOR.CLASS.IDENTIFIER
+255 constant OPTION.END
+
+: discover ( a )
+ dup >Remote.address IPv4bcast swap IPADDRESSLENGTH cmove
+ TODO add hostname OPTION.HOSTNAME option
+ TODO add " plan9_amd64" OPTION.VENDOR.CLASS.IDENTIFIER option
+ TODO add requeted OPTION.PARAMETER_REQUEST_LIST option
+ TODO add requeted OPTION.REQUESTED_IP_ADDRESS Local option
+
+: request ( a )
+ Phase @
+ dup RENEWING = if renew else
+ dup REBINDING = if rebind else
+ dup REQUESTING = if request else
+ then then then drop
+ dup >Remote.address IPv4bcast swap IPADDRESSLENGTH cmove
+ TODO add hostname OPTION.HOSTNAME option
+ TODO add " plan9_amd64" OPTION.VENDOR.CLASS.IDENTIFIER option
+ TODO add requeted OPTION.PARAMETER_REQUEST_LIST option
+ TODO add requeted OPTION.REQUESTED_IP_ADDRESS Local option
+
+: release ( a )
+ send raddr
+ v6tov4 ciaddr
+ TODO add requeted OPTION.REQUESTED_IP_ADDRESS Local option
+ TODO add Serverid requeted OPTION.REQUESTED_IP_ADDRESS Local option
+
+: build ( type a -- ) \ build the dhcp message at a
+ dup >Rport 67 2 hnput
+ BOOTREQUEST over >Op c!
+ dup >Xid Xid @ 4 hnput
+ dup >Secs
+ time Starttime @ -
+ 2 hnput
+ dup >Flags 0 2 hnput
+ dup >Magic >r 99 83 130 99 r> 4 put
+ dup >Chaddr Hardware.address swap Hardware.address.length cmove
+ dup >Htype Hardware.type @ swap c!
+ dup >Hlen Hardware.address.length @ swap c!
+ 2dup ( type a type a ) >Optiondata swap c!
+ swap ( a type )
+ dup DISCOVER = if drop discover else
+ dup REQUEST = if drop request else
+ dup RELEASE = if drop release else
+ ." dhcpsend: unknown message type" emit terminate
+ then then then
+ TODO add OPTION.END option
+
+: dhcpsend ( type -- )
+ pad dup erase ( a ) build send
+
+timer
+ time Timeout @ < if exit then
+ Phase @
+ dup INIT = if exit then
+ dup BOUND = if exit then
+ dup SELECTING =
+ over REQUESTING = or
+ over REBINDING = or
+ if Phase @ SELECTING = if discover else request then
+ time 4 + Timeout !
+ Resend 1+ Resend @ 5 > if INIT Phase ! then
+ then
+ dup RENEWING = if
+ time 1 + Timeout !
+ Resend 1+ Resend @ 3 > if REBINDING Phase ! 0 Resend ! then
+ then
+
+correspond
+ Xid !
+ Start !
+ Phase !
+ ask
+ 0 Resend !
+ time 4 + Timeout !
+ begin
+ receive timer
+ Phase @ dup SBOUND != swap SINIT != and
+ until
+
+configure
+ add ipnoaddr ipnoaddr send
+ correspond
+ remove ipnoaddr ipnoaddr send
+
+void
+dhcpquery(int needconfig, int startstate)
+{
+ if(needconfig)
+ addnulladdr();
+
+ conf.fd = openlisten();
+ if(conf.fd < 0){
+ conf.state = Sinit;
+ return;
+ }
+ notify(catch);
+
+ conf.xid = lrand();
+ conf.starttime = time(0);
+ conf.state = startstate;
+ switch(startstate){
+ case Sselecting:
+ conf.offered = 0;
+ dhcpsend(Discover);
+ break;
+ case Srenewing:
+ dhcpsend(Request);
+ break;
+ default:
+ sysfatal("internal error 0");
+ }
+ conf.resend = 0;
+ conf.timeout = time(0) + 4;
+
+ while(conf.state != Sbound && conf.state != Sinit){
+ dhcprecv();
+ dhcptimer();
+ }
+ close(conf.fd);
+
+ if(needconfig)
+ removenulladdr();
+}
+static void
+dhcptimer(void)
+{
+ ulong now;
+
+ now = time(0);
+ if(now < conf.timeout)
+ return;
+
+ switch(conf.state) {
+ default:
+ sysfatal("dhcptimer: unknown state %d", conf.state);
+ case Sinit:
+ case Sbound:
+ break;
+ case Sselecting:
+ case Srequesting:
+ case Srebinding:
+ dhcpsend(conf.state == Sselecting? Discover: Request);
+ conf.timeout = now + 4;
+ if(++conf.resend > 5)
+ conf.state = Sinit;
+ break;
+ case Srenewing:
+ dhcpsend(Request);
+ conf.timeout = now + 1;
+ if(++conf.resend > 3) {
+ conf.state = Srebinding;
+ conf.resend = 0;
+ }
+ break;
+ }
+}
+
+static void
+dhcpsend(int type)
+{
+ Bootp bp;
+ uchar *p;
+ int n;
+ uchar vendor[64];
+ Udphdr *up = (Udphdr*)bp.udphdr;
+
+ memset(&bp, 0, sizeof bp);
+
+ hnputs(up->rport, 67);
+ bp.op = Bootrequest;
+ hnputl(bp.xid, conf.xid);
+ hnputs(bp.secs, time(0)-conf.starttime);
+ hnputs(bp.flags, 0);
+ memmove(bp.optmagic, optmagic, 4);
+ if(conf.hwatype >= 0 && conf.hwalen < sizeof bp.chaddr){
+ memmove(bp.chaddr, conf.hwa, conf.hwalen);
+ bp.hlen = conf.hwalen;
+ bp.htype = conf.hwatype;
+ }
+ p = bp.optdata;
+ p = optaddbyte(p, ODtype, type);
+ p = optadd(p, ODclientid, conf.cid, conf.cidlen);
+ switch(type) {
+ default:
+ sysfatal("dhcpsend: unknown message type: %d", type);
+ case Discover:
+ ipmove(up->raddr, IPv4bcast); /* broadcast */
+ if(*conf.hostname && sendhostname)
+ p = optaddstr(p, OBhostname, conf.hostname);
+ if(plan9){
+ n = snprint((char*)vendor, sizeof vendor,
+ "plan9_%s", conf.cputype);
+ p = optaddvec(p, ODvendorclass, vendor, n);
+ }
+ p = optaddvec(p, ODparams, requested, nrequested);
+ if(validip(conf.laddr))
+ p = optaddaddr(p, ODipaddr, conf.laddr);
+ break;
+ case Request:
+ switch(conf.state){
+ case Srenewing:
+ ipmove(up->raddr, conf.server);
+ v6tov4(bp.ciaddr, conf.laddr);
+ break;
+ case Srebinding:
+ ipmove(up->raddr, IPv4bcast); /* broadcast */
+ v6tov4(bp.ciaddr, conf.laddr);
+ break;
+ case Srequesting:
+ ipmove(up->raddr, IPv4bcast); /* broadcast */
+ p = optaddaddr(p, ODipaddr, conf.laddr);
+ p = optaddaddr(p, ODserverid, conf.server);
+ break;
+ }
+ p = optaddulong(p, ODlease, conf.offered);
+ if(plan9){
+ n = snprint((char*)vendor, sizeof vendor,
+ "plan9_%s", conf.cputype);
+ p = optaddvec(p, ODvendorclass, vendor, n);
+ }
+ p = optaddvec(p, ODparams, requested, nrequested);
+ if(*conf.hostname && sendhostname)
+ p = optaddstr(p, OBhostname, conf.hostname);
+ break;
+ case Release:
+ ipmove(up->raddr, conf.server);
+ v6tov4(bp.ciaddr, conf.laddr);
+ p = optaddaddr(p, ODipaddr, conf.laddr);
+ p = optaddaddr(p, ODserverid, conf.server);
+ break;
+ }
+
+ *p++ = OBend;
+
+ n = p - (uchar*)&bp;
+ USED(n);
+
+ /*
+ * We use a maximum size DHCP packet to survive the
+ * All_Aboard NAT package from Internet Share. It
+ * always replies to DHCP requests with a packet of the
+ * same size, so if the request is too short the reply
+ * is truncated.
+ */
+ if(write(conf.fd, &bp, sizeof bp) != sizeof bp)
+ warning("dhcpsend: write failed: %r");
+}
+
+static void
+dhcprecv(void)
+{
+ int i, n, type;
+ ulong lease;
+ char err[ERRMAX];
+ uchar buf[8000], vopts[256], taddr[IPaddrlen];
+ Bootp *bp;
+
+ memset(buf, 0, sizeof buf);
+ alarm(1000);
+ n = read(conf.fd, buf, sizeof buf);
+ alarm(0);
+
+ if(n < 0){
+ rerrstr(err, sizeof err);
+ if(strstr(err, "interrupt") == nil)
+ warning("dhcprecv: bad read: %s", err);
+ else
+ DEBUG("dhcprecv: read timed out");
+ return;
+ }
+
+ bp = parsebootp(buf, n);
+ if(bp == 0) {
+ DEBUG("parsebootp failed: dropping packet");
+ return;
+ }
+
+ type = optgetbyte(bp->optdata, ODtype);
+ switch(type) {
+ default:
+ warning("dhcprecv: unknown type: %d", type);
+ break;
+ case Offer:
+ DEBUG("got offer from %V ", bp->siaddr);
+ if(conf.state != Sselecting)
+ break;
+ lease = optgetulong(bp->optdata, ODlease);
+ if(lease == 0){
+ /*
+ * The All_Aboard NAT package from Internet Share
+ * doesn't give a lease time, so we have to assume one.
+ */
+ warning("Offer with %lud lease, using %d", lease, MinLease);
+ lease = MinLease;
+ }
+ DEBUG("lease=%lud ", lease);
+ if(!optgetaddr(bp->optdata, ODserverid, conf.server)) {
+ warning("Offer from server with invalid serverid");
+ break;
+ }
+
+ v4tov6(conf.laddr, bp->yiaddr);
+ memmove(conf.sname, bp->sname, sizeof conf.sname);
+ conf.sname[sizeof conf.sname-1] = 0;
+ DEBUG("server=%I sname=%s", conf.server, conf.sname);
+ conf.offered = lease;
+ conf.state = Srequesting;
+ dhcpsend(Request);
+ conf.resend = 0;
+ conf.timeout = time(0) + 4;
+ break;
+ case Ack:
+ DEBUG("got ack from %V ", bp->siaddr);
+ if (conf.state != Srequesting && conf.state != Srenewing &&
+ conf.state != Srebinding)
+ break;
+
+ /* ignore a bad lease */
+ lease = optgetulong(bp->optdata, ODlease);
+ if(lease == 0){
+ /*
+ * The All_Aboard NAT package from Internet Share
+ * doesn't give a lease time, so we have to assume one.
+ */
+ warning("Ack with %lud lease, using %d", lease, MinLease);
+ lease = MinLease;
+ }
+ DEBUG("lease=%lud ", lease);
+
+ /* address and mask */
+ if(!validip(conf.laddr) || !Oflag)
+ v4tov6(conf.laddr, bp->yiaddr);
+ if(!validip(conf.mask) || !Oflag){
+ if(!optgetaddr(bp->optdata, OBmask, conf.mask))
+ ipmove(conf.mask, IPnoaddr);
+ if(ipcmp(conf.mask, IPv4bcast) == 0)
+ ipmove(conf.mask, IPnoaddr);
+ }
+ DEBUG("ipaddr=%I ipmask=%M ", conf.laddr, conf.mask);
+
+ /*
+ * get a router address either from the router option
+ * or from the router that forwarded the dhcp packet
+ */
+ if(validip(conf.gaddr) && Oflag) {
+ DEBUG("ipgw=%I ", conf.gaddr);
+ } else if(optgetaddr(bp->optdata, OBrouter, conf.gaddr)){
+ DEBUG("ipgw=%I ", conf.gaddr);
+ } else if(memcmp(bp->giaddr, IPnoaddr+IPv4off, IPv4addrlen)!=0){
+ v4tov6(conf.gaddr, bp->giaddr);
+ DEBUG("giaddr=%I ", conf.gaddr);
+ }
+
+ /* get dns servers */
+ memset(conf.dns, 0, sizeof conf.dns);
+ n = optgetaddrs(bp->optdata, OBdnserver, conf.dns,
+ sizeof conf.dns/IPaddrlen);
+ for(i = 0; i < n; i++)
+ DEBUG("dns=%I ", conf.dns + i*IPaddrlen);
+
+ /* get ntp servers */
+ memset(conf.ntp, 0, sizeof conf.ntp);
+ n = optgetaddrs(bp->optdata, OBntpserver, conf.ntp,
+ sizeof conf.ntp/IPaddrlen);
+ for(i = 0; i < n; i++)
+ DEBUG("ntp=%I ", conf.ntp + i*IPaddrlen);
+
+ /* get names */
+ if(optgetstr(bp->optdata, OBhostname,
+ conf.hostname, sizeof conf.hostname))
+ DEBUG("hostname=%s ", conf.hostname);
+ if(optgetstr(bp->optdata, OBdomainname,
+ conf.domainname, sizeof conf.domainname))
+ DEBUG("domainname=%s ", conf.domainname);
+ if(optgetnames(bp->optdata, ODdnsdomain,
+ conf.dnsdomain, sizeof conf.dnsdomain))
+ DEBUG("dnsdomain=%s ", conf.dnsdomain);
+
+ /* get anything else we asked for */
+ getoptions(bp->optdata);
+
+ /* get plan9-specific options */
+ n = optgetvec(bp->optdata, OBvendorinfo, vopts, sizeof vopts-1);
+ if(n > 0 && parseoptions(vopts, n) == 0){
+ if(validip(conf.fs) && Oflag)
+ n = 1;
+ else {
+ n = optgetp9addrs(vopts, OP9fs, conf.fs, 2);
+ if (n == 0)
+ n = optgetaddrs(vopts, OP9fsv4,
+ conf.fs, 2);
+ }
+ for(i = 0; i < n; i++)
+ DEBUG("fs=%I ", conf.fs + i*IPaddrlen);
+
+ if(validip(conf.auth) && Oflag)
+ n = 1;
+ else {
+ n = optgetp9addrs(vopts, OP9auth, conf.auth, 2);
+ if (n == 0)
+ n = optgetaddrs(vopts, OP9authv4,
+ conf.auth, 2);
+ }
+ for(i = 0; i < n; i++)
+ DEBUG("auth=%I ", conf.auth + i*IPaddrlen);
+
+ n = optgetp9addrs(vopts, OP9ipaddr, taddr, 1);
+ if (n > 0)
+ ipmove(conf.laddr, taddr);
+ n = optgetp9addrs(vopts, OP9ipmask, taddr, 1);
+ if (n > 0)
+ ipmove(conf.mask, taddr);
+ n = optgetp9addrs(vopts, OP9ipgw, taddr, 1);
+ if (n > 0)
+ ipmove(conf.gaddr, taddr);
+ DEBUG("new ipaddr=%I new ipmask=%M new ipgw=%I",
+ conf.laddr, conf.mask, conf.gaddr);
+ }
+ conf.lease = lease;
+ conf.state = Sbound;
+ DEBUG("server=%I sname=%s", conf.server, conf.sname);
+ break;
+ case Nak:
+ conf.state = Sinit;
+ warning("recved dhcpnak on %s", conf.mpoint);
+ break;
+ }
+}
--- a/forth/helpers.f
+++ b/forth/helpers.f
@@ -26,7 +26,7 @@
>r count cstring1 >r count cstring0 r> r> sysbind ;
: sbind ( 'new nnew 'old nold flags -- )
- >r >r >r \ ( 'new nnew ) (R flags nold 'old )
- cstring0 \ ( 'padtext-new ) (R flags nold 'old )
- r> r> cstring1 \ ( 'padtext_new 'padtext_old ) (R flags )
+ >r >r >r ( 'new nnew ) (R flags nold 'old )
+ cstring0 ( 'padtext-new ) (R flags nold 'old )
+ r> r> cstring1 ( 'padtext_new 'padtext_old ) (R flags )
r> sysbind ;
--- a/forth/ns.f
+++ b/forth/ns.f
@@ -1,17 +1,3 @@
-: ioerror ( n -- ) ." ioerror: " . cr ;
+include /forth/cat.f
-: show ( read_count -- )
- dup 0 < if ioerror then
- pad swap ( 'pad read_count ) type ;
-
-: untileof ( fd -- fd )
- begin
- dup pad 1024 sysread ( fd read_count )
- ?dup while show ( fd )
- repeat ;
-
-: ns s" #p/1/ns" cstring0 r/o sysopen ( fd )
- dup -1 > ( fd fd>=0? )
- if ( fd ) untileof sysclose drop
- else ." open error: " .
- then ;
+: ns s" #p/1/ns" scat ;
--- a/os/pc64/pc64
+++ b/os/pc64/pc64
@@ -194,6 +194,7 @@
/dis/wm
/osinit.dis
/init.f
+ /forth/cat.f
/forth/helpers.f
/forth/ns.f
# for custom initialization and shutdown
--- a/os/pc64/primitives-nasm.s
+++ b/os/pc64/primitives-nasm.s
@@ -96,7 +96,6 @@
MVENTRY "Errfd" Errfd 5
MVENTRY "Eof" Eof 3
MVENTRY "Ninputs" Ninputs 7
-MVENTRY "H0" H0 2 ; here at startup
MVENTRY "Bufferfds" Bufferfds 9 16
MVENTRY "Bufferfilenames" Bufferfilenames 15 16 ; counted string labels of the searchers populated by boot
--- a/os/pc64/words-nasm.s
+++ b/os/pc64/words-nasm.s
@@ -1573,8 +1573,8 @@
dd C_comma ; store n into the dictionary
dd M_exitcolon
-CENTRY "immediate" C_immediate 9
-dd MV_Dp
+CENTRY "immediate" C_immediate 9 ; set immediate flag on the latest defined dictionary entry
+dd MV_Dtop
dd M_fetch
dd C_cell_plus
dd M_dup
@@ -1585,6 +1585,7 @@
dd M_xswap
dd M_cstore
dd M_exitcolon
+
CENTRY ">cfa" C_tocfa 4
dd C_count
dd M_literal
@@ -1671,8 +1672,9 @@
dd MV_State
dd C_off
dd M_exitcolon
+
CENTRY "smudge" C_smudge 6
-dd MV_Dp
+dd MV_Dtop
dd M_fetch
dd C_cell_plus
dd M_dup
@@ -1683,8 +1685,9 @@
dd M_xswap
dd M_cstore
dd M_exitcolon
+
CENTRY "reveal" C_reveal 6
-dd MV_Dp
+dd MV_Dtop
dd M_fetch
dd C_cell_plus
dd M_dup
@@ -1722,7 +1725,7 @@
dd M_exitcolon
CIENTRY "recurse" CI_recurse 7
-dd MV_Dp
+dd MV_Dtop
dd M_fetch
dd C_cell_plus
dd C_tocfa
@@ -2259,10 +2262,6 @@
dd C_parenabort ; ( (abort) -- )
dd MV_Abortvec ; variable that puts (abort) code address on the stack
dd M_store ; variable abortvec = (abort) code address
-
-dd MV_Dp
-dd MV_H0 ; H0 = here at startup
-dd M_store
dd MC_STDIN
dd MV_Infd ; might be overwritten by args below