Browse Source

Plan 9 from Bell Labs 2005-02-04

David du Colombier 16 years ago
parent
commit
082eb2e4c4

+ 37 - 24
dist/replica/_plan9.db

@@ -3,19 +3,19 @@
 386/9loaddebug - 775 sys sys 1106021711 306647
 386/9loadlite - 775 sys sys 1100269949 132260
 386/9loadlitedebug - 775 sys sys 1104122096 195560
-386/9pc - 775 sys sys 1107061082 1833682
+386/9pc - 775 sys sys 1107405606 1833830
 386/9pc.gz - 664 sys sys 1077049336 635727
-386/9pccpu - 775 sys sys 1107061085 1488624
+386/9pccpu - 775 sys sys 1107405611 1488772
 386/9pccpu.gz - 664 sys sys 1077049387 519909
-386/9pcdisk - 775 sys sys 1107061089 2039384
+386/9pcdisk - 775 sys sys 1107405618 2039532
 386/9pcdisk.gz - 664 sys sys 1040006345 703136
-386/9pcf - 775 sys sys 1107061093 2382216
+386/9pcf - 775 sys sys 1107405626 2382364
 386/9pcf.gz - 664 sys sys 1077049490 872650
 386/9pxeload - 775 sys sys 1100269949 208708
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin/8a - 775 sys sys 1104121953 114832
-386/bin/8c - 775 sys sys 1104121954 357649
+386/bin/8c - 775 sys sys 1107405596 357746
 386/bin/8l - 775 sys sys 1104121955 114930
 386/bin/9660srv - 775 sys sys 1104121955 103973
 386/bin/aan - 775 sys sys 1104121955 130710
@@ -58,7 +58,7 @@
 386/bin/auth/guard.srv - 775 sys sys 1104121964 142850
 386/bin/auth/iam - 775 sys sys 1085076981 50791
 386/bin/auth/keyfs - 775 sys sys 1106107675 115351
-386/bin/auth/login - 775 sys sys 1104121965 103362
+386/bin/auth/login - 775 sys sys 1107405597 103379
 386/bin/auth/newns - 775 sys sys 1104121965 87950
 386/bin/auth/none - 775 sys sys 1104121966 87699
 386/bin/auth/pemdecode - 775 sys sys 1104121966 61457
@@ -437,7 +437,7 @@
 386/bin/upas/bayes - 775 sys sys 1064598344 70530
 386/bin/upas/deliver - 775 sys sys 1104122069 99781
 386/bin/upas/filter - 775 sys sys 1104122070 147311
-386/bin/upas/fs - 775 sys sys 1104122070 332354
+386/bin/upas/fs - 775 sys sys 1107405598 332387
 386/bin/upas/isspam - 775 sys sys 1064598349 38
 386/bin/upas/list - 775 sys sys 1104122071 82776
 386/bin/upas/marshal - 775 sys sys 1104122071 132491
@@ -4425,7 +4425,7 @@ sys/lib/sysconfig/auth/files/tcp566 - 775 sys sys 1016833537 36
 sys/lib/sysconfig/auth/files/tcp567 - 775 sys sys 1016833537 34
 sys/lib/sysconfig/auth/mkfile - 664 sys sys 1016833657 2937
 sys/lib/sysconfig/blast - 20000000775 sys sys 1059490895 0
-sys/lib/sysconfig/blast/boot - 775 sys sys 1100701674 568
+sys/lib/sysconfig/blast/boot - 775 sys sys 1107436263 568
 sys/lib/sysconfig/proto - 20000000775 sys sys 959740591 0
 sys/lib/sysconfig/proto/allproto - 664 sys sys 945018241 2
 sys/lib/sysconfig/proto/armpaqproto - 664 sys sys 1089299189 2230
@@ -5123,7 +5123,7 @@ sys/man/8/nfsserver - 664 sys sys 1017251291 3397
 sys/man/8/pcmcia - 664 sys sys 944959679 408
 sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/ping - 664 sys sys 1084473185 3436
-sys/man/8/plan9.ini - 664 sys sys 1094650551 20806
+sys/man/8/plan9.ini - 664 sys sys 1107448255 21148
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/ppp - 664 sys sys 1096036494 4424
 sys/man/8/prep - 664 sys sys 1079705872 13820
@@ -5273,7 +5273,7 @@ sys/src/9/boot/bootmkfile - 664 sys sys 1091732792 404
 sys/src/9/boot/doauthenticate.c - 664 sys sys 1015012529 2300
 sys/src/9/boot/embed.c - 664 sys sys 1039763720 1191
 sys/src/9/boot/getpasswd.c - 664 sys sys 957373373 654
-sys/src/9/boot/local.c - 664 sys sys 1105976808 5619
+sys/src/9/boot/local.c - 664 sys sys 1107436091 5619
 sys/src/9/boot/mkboot - 775 sys sys 1045504382 1935
 sys/src/9/boot/nopsession.c - 664 sys sys 957373374 843
 sys/src/9/boot/paq.c - 664 sys sys 1067722601 1099
@@ -5391,7 +5391,7 @@ sys/src/9/pc/ethermii.h - 664 sys sys 1086873891 3258
 sys/src/9/pc/etherrhine.c - 664 sys sys 1081706478 13799
 sys/src/9/pc/ethersink.c - 664 sys sys 1048644103 1076
 sys/src/9/pc/ethersmc.c - 664 sys sys 1071245461 15103
-sys/src/9/pc/etherwavelan.c - 664 sys sys 1026847642 3722
+sys/src/9/pc/etherwavelan.c - 664 sys sys 1107448246 3723
 sys/src/9/pc/floppy.h - 664 sys sys 1055700609 3835
 sys/src/9/pc/fns.h - 664 sys sys 1089046996 4372
 sys/src/9/pc/hcwAMC.h - 664 sys sys 1026860163 166004
@@ -5420,7 +5420,7 @@ sys/src/9/pc/pcdisk - 664 sys sys 1073851851 1427
 sys/src/9/pc/pcf - 664 sys sys 1104430623 1485
 sys/src/9/pc/pcfl - 664 sys sys 1042004821 1563
 sys/src/9/pc/pcflop - 664 sys sys 1104430611 1438
-sys/src/9/pc/pci.c - 664 sys sys 1096379063 25817
+sys/src/9/pc/pci.c - 664 sys sys 1107436009 25850
 sys/src/9/pc/pcmciamodem.c - 664 sys sys 1099761153 1586
 sys/src/9/pc/piix4smbus.c - 664 sys sys 1091129037 5230
 sys/src/9/pc/plan9l.s - 664 sys sys 1015014521 910
@@ -5434,7 +5434,7 @@ sys/src/9/pc/screen.h - 664 sys sys 1060267144 3797
 sys/src/9/pc/sd53c8xx.c - 664 sys sys 1086987325 52219
 sys/src/9/pc/sd53c8xx.i - 664 sys sys 1045063730 27355
 sys/src/9/pc/sd53c8xx.n - 664 sys sys 1032059019 12455
-sys/src/9/pc/sdata.c - 664 sys sys 1099487462 50970
+sys/src/9/pc/sdata.c - 664 sys sys 1107436009 51019
 sys/src/9/pc/sdmylex.c - 664 sys sys 1071245460 27812
 sys/src/9/pc/sdscsi.c - 664 sys sys 1077033661 7487
 sys/src/9/pc/trap.c - 664 sys sys 1105109602 20537
@@ -5466,8 +5466,8 @@ sys/src/9/pc/vgatvp3020.c - 664 sys sys 1015014528 4491
 sys/src/9/pc/vgatvp3026.c - 664 sys sys 1015014528 3940
 sys/src/9/pc/vgavmware.c - 664 sys sys 1063858321 6398
 sys/src/9/pc/vgax.c - 664 sys sys 1015014528 1655
-sys/src/9/pc/wavelan.c - 664 sys sys 1056299581 27253
-sys/src/9/pc/wavelan.h - 664 sys sys 1055700615 6151
+sys/src/9/pc/wavelan.c - 664 sys sys 1107448246 27838
+sys/src/9/pc/wavelan.h - 664 sys sys 1107448246 6169
 sys/src/9/port - 20000000775 sys sys 1018469625 0
 sys/src/9/port/alarm.c - 664 sys sys 1067722766 1426
 sys/src/9/port/alloc.c - 664 sys sys 1102093389 5645
@@ -5555,7 +5555,7 @@ sys/src/9/port/tod.c - 664 sys sys 1067722762 4856
 sys/src/9/port/unthwack.c - 664 sys sys 1057323394 5249
 sys/src/9/port/xalloc.c - 664 sys sys 1097074047 4030
 sys/src/9/ppc - 20000000775 sys sys 1059490838 0
-sys/src/9/ppc/blast - 664 sys sys 1100701674 685
+sys/src/9/ppc/blast - 664 sys sys 1107436310 670
 sys/src/9/ppc/blast.h - 664 sys sys 1059490750 3109
 sys/src/9/ppc/clock.c - 664 sys sys 1100701675 1036
 sys/src/9/ppc/dat.h - 664 sys sys 1097073353 4712
@@ -7058,11 +7058,17 @@ sys/src/cmd/aux/flashfs/mkit - 775 sys sys 1015009082 86
 sys/src/cmd/aux/flashfs/request.c - 664 sys sys 1019507619 5739
 sys/src/cmd/aux/flashfs/testld.c - 664 sys sys 1015009082 1043
 sys/src/cmd/aux/flashfs/utils.c - 664 sys sys 1019498850 1097
+sys/src/cmd/aux/gps - 20000000775 sys sys 1107448949 0
+sys/src/cmd/aux/gps/dat.h - 664 sys sys 1107448949 287
+sys/src/cmd/aux/gps/gpsevermore.c - 664 sys sys 1107448815 4501
+sys/src/cmd/aux/gps/gpsfs.c - 664 sys sys 1107448815 16152
+sys/src/cmd/aux/gps/mkfile - 664 sys sys 1107448949 234
+sys/src/cmd/aux/gps/util.c - 664 sys sys 1107448815 2795
 sys/src/cmd/aux/lines.c - 664 sys sys 1015008782 546
 sys/src/cmd/aux/lis - 775 sys sys 944960794 45
 sys/src/cmd/aux/listen.c - 664 sys sys 1093452954 8142
 sys/src/cmd/aux/listen1.c - 664 sys sys 1093452955 2018
-sys/src/cmd/aux/mkfile - 664 sys sys 1105123164 962
+sys/src/cmd/aux/mkfile - 664 sys sys 1107448969 968
 sys/src/cmd/aux/mklatinkbd.c - 664 sys sys 953253425 3813
 sys/src/cmd/aux/mnihongo - 20000000775 sys sys 944960789 0
 sys/src/cmd/aux/mnihongo/README - 664 sys sys 944960789 475
@@ -7085,7 +7091,7 @@ sys/src/cmd/aux/rdwr.c - 664 sys sys 1016833876 811
 sys/src/cmd/aux/reboot.c - 664 sys sys 1014925091 1411
 sys/src/cmd/aux/searchfs.c - 664 sys sys 1014925091 18176
 sys/src/cmd/aux/stub.c - 664 sys sys 1098196222 2723
-sys/src/cmd/aux/timesync.c - 664 sys sys 1083697436 24772
+sys/src/cmd/aux/timesync.c - 664 sys sys 1107448970 25758
 sys/src/cmd/aux/trampoline.c - 664 sys sys 1078840013 3521
 sys/src/cmd/aux/typepasswd.c - 664 sys sys 1014925091 1761
 sys/src/cmd/aux/unlock - 664 sys sys 944960793 0
@@ -10802,6 +10808,7 @@ sys/src/cmd/unix/u9fs/utfrune.c - 664 sys sys 1015092354 387
 sys/src/cmd/unix/winplumb.c - 664 sys sys 1047233509 5015
 sys/src/cmd/unix/winplumb.exe - 664 sys sys 1047233509 32768
 sys/src/cmd/unix/winstart - 775 sys sys 1047233540 60
+sys/src/cmd/unlnfs.c - 664 sys sys 1107435471 1949
 sys/src/cmd/unmount.c - 664 sys sys 1014926615 442
 sys/src/cmd/upas - 20000000775 sys sys 1018549518 0
 sys/src/cmd/upas/README - 664 sys sys 944961329 1041
@@ -10859,7 +10866,7 @@ sys/src/cmd/upas/fs/readdir.c - 664 sys sys 944961331 203
 sys/src/cmd/upas/fs/strtotm.c - 664 sys sys 1041137528 1904
 sys/src/cmd/upas/fs/tester.c - 664 sys sys 985037420 1418
 sys/src/cmd/upas/marshal - 20000000775 sys sys 1015009721 0
-sys/src/cmd/upas/marshal/marshal.c - 664 sys sys 1089299189 32566
+sys/src/cmd/upas/marshal/marshal.c - 664 sys sys 1107435333 32664
 sys/src/cmd/upas/marshal/mkfile - 664 sys sys 1047490298 235
 sys/src/cmd/upas/misc - 20000000775 sys sys 944961318 0
 sys/src/cmd/upas/misc/gone.fishing - 664 sys sys 944961318 313
@@ -11344,12 +11351,12 @@ sys/src/games/music/mkfile - 664 sys sys 1103793915 723
 sys/src/games/music/mkinc - 664 sys sys 1103793915 92
 sys/src/games/music/playlistfs - 20000000775 sys sys 1103794221 0
 sys/src/games/music/playlistfs/boilerplate.c - 664 sys sys 1105531426 1362
-sys/src/games/music/playlistfs/fs.c - 664 sys sys 1103793922 18071
+sys/src/games/music/playlistfs/fs.c - 664 sys sys 1107436434 17485
 sys/src/games/music/playlistfs/main.c - 664 sys sys 1103793922 1636
 sys/src/games/music/playlistfs/mk.dep - 664 sys sys 1103793923 594
 sys/src/games/music/playlistfs/mkfile - 664 sys sys 1103793923 187
 sys/src/games/music/playlistfs/player.c - 664 sys sys 1103793923 10228
-sys/src/games/music/playlistfs/playlist.h - 664 sys sys 1103793923 2608
+sys/src/games/music/playlistfs/playlist.h - 664 sys sys 1107436453 2579
 sys/src/games/music/playlistfs/playplumb.c - 664 sys sys 1103793924 280
 sys/src/games/music/playlistfs/volume.c - 664 sys sys 1103793924 2065
 sys/src/games/music/readcd - 775 sys sys 1103793915 996
@@ -12456,6 +12463,12 @@ usr/glenda/lib/profile - 664 glenda glenda 1105128663 890
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
-386/bin/8c - 775 sys sys 1107403546 357746
-386/bin/auth/login - 775 sys sys 1107403546 103379
-386/bin/upas/fs - 775 sys sys 1107403547 332387
+386/9pc - 775 sys sys 1107490489 1834244
+386/9pccpu - 775 sys sys 1107490494 1488803
+386/9pcdisk - 775 sys sys 1107490498 2039946
+386/9pcf - 775 sys sys 1107490504 2382778
+386/bin/aux/gpsevermore - 775 sys sys 1107490157 71417
+386/bin/aux/gpsfs - 775 sys sys 1107490157 174347
+386/bin/aux/timesync - 775 sys sys 1107490157 128213
+386/bin/unlnfs - 775 sys sys 1107490157 71362
+386/bin/upas/marshal - 775 sys sys 1107490159 132595

+ 33 - 23
dist/replica/plan9.db

@@ -3,19 +3,19 @@
 386/9loaddebug - 775 sys sys 1106021711 306647
 386/9loadlite - 775 sys sys 1100269949 132260
 386/9loadlitedebug - 775 sys sys 1104122096 195560
-386/9pc - 775 sys sys 1107061082 1833682
+386/9pc - 775 sys sys 1107490489 1834244
 386/9pc.gz - 664 sys sys 1077049336 635727
-386/9pccpu - 775 sys sys 1107061085 1488624
+386/9pccpu - 775 sys sys 1107490494 1488803
 386/9pccpu.gz - 664 sys sys 1077049387 519909
-386/9pcdisk - 775 sys sys 1107061089 2039384
+386/9pcdisk - 775 sys sys 1107490498 2039946
 386/9pcdisk.gz - 664 sys sys 1040006345 703136
-386/9pcf - 775 sys sys 1107061093 2382216
+386/9pcf - 775 sys sys 1107490504 2382778
 386/9pcf.gz - 664 sys sys 1077049490 872650
 386/9pxeload - 775 sys sys 1100269949 208708
 386/_9pcdisk.gz - 664 sys sys 1039764191 695837
 386/bin - 20000000775 sys sys 1018897690 0
 386/bin/8a - 775 sys sys 1104121953 114832
-386/bin/8c - 775 sys sys 1107403546 357746
+386/bin/8c - 775 sys sys 1107405596 357746
 386/bin/8l - 775 sys sys 1104121955 114930
 386/bin/9660srv - 775 sys sys 1104121955 103973
 386/bin/aan - 775 sys sys 1104121955 130710
@@ -58,7 +58,7 @@
 386/bin/auth/guard.srv - 775 sys sys 1104121964 142850
 386/bin/auth/iam - 775 sys sys 1085076981 50791
 386/bin/auth/keyfs - 775 sys sys 1106107675 115351
-386/bin/auth/login - 775 sys sys 1107403546 103379
+386/bin/auth/login - 775 sys sys 1107405597 103379
 386/bin/auth/newns - 775 sys sys 1104121965 87950
 386/bin/auth/none - 775 sys sys 1104121966 87699
 386/bin/auth/pemdecode - 775 sys sys 1104121966 61457
@@ -101,6 +101,8 @@
 386/bin/aux/flashfs - 775 sys sys 1104121976 160286
 386/bin/aux/g3p9bit - 775 sys sys 1104121976 67278
 386/bin/aux/getflags - 775 sys sys 1104121977 43817
+386/bin/aux/gpsevermore - 775 sys sys 1107490157 71417
+386/bin/aux/gpsfs - 775 sys sys 1107490157 174347
 386/bin/aux/grabit - 775 sys sys 1020319063 1244
 386/bin/aux/hardcopy - 775 sys sys 1020319063 1699
 386/bin/aux/isvmware - 775 sys sys 1032486791 23997
@@ -141,7 +143,7 @@
 386/bin/aux/stub - 775 sys sys 1104121986 135062
 386/bin/aux/tcpostio - 775 sys sys 1094040084 200808
 386/bin/aux/text2post - 775 sys sys 1104121986 78336
-386/bin/aux/timesync - 775 sys sys 1104121987 127215
+386/bin/aux/timesync - 775 sys sys 1107490157 128213
 386/bin/aux/tr2post - 775 sys sys 1104121987 176578
 386/bin/aux/trampoline - 775 sys sys 1104121988 83293
 386/bin/aux/typepasswd - 775 sys sys 1104121988 69503
@@ -429,6 +431,7 @@
 386/bin/unicode - 775 sys sys 1104122068 62523
 386/bin/uniq - 775 sys sys 1104122068 61900
 386/bin/units - 775 sys sys 1104122068 75250
+386/bin/unlnfs - 775 sys sys 1107490157 71362
 386/bin/unmount - 775 sys sys 1104122068 36611
 386/bin/unzip - 775 sys sys 1104122069 89733
 386/bin/upas - 20000000775 sys sys 1016857390 0
@@ -437,10 +440,10 @@
 386/bin/upas/bayes - 775 sys sys 1064598344 70530
 386/bin/upas/deliver - 775 sys sys 1104122069 99781
 386/bin/upas/filter - 775 sys sys 1104122070 147311
-386/bin/upas/fs - 775 sys sys 1107403547 332387
+386/bin/upas/fs - 775 sys sys 1107405598 332387
 386/bin/upas/isspam - 775 sys sys 1064598349 38
 386/bin/upas/list - 775 sys sys 1104122071 82776
-386/bin/upas/marshal - 775 sys sys 1104122071 132491
+386/bin/upas/marshal - 775 sys sys 1107490159 132595
 386/bin/upas/ml - 775 sys sys 1104122072 123499
 386/bin/upas/mlmgr - 775 sys sys 1104122072 104185
 386/bin/upas/mlowner - 775 sys sys 1104122072 92108
@@ -4425,7 +4428,7 @@ sys/lib/sysconfig/auth/files/tcp566 - 775 sys sys 1016833537 36
 sys/lib/sysconfig/auth/files/tcp567 - 775 sys sys 1016833537 34
 sys/lib/sysconfig/auth/mkfile - 664 sys sys 1016833657 2937
 sys/lib/sysconfig/blast - 20000000775 sys sys 1059490895 0
-sys/lib/sysconfig/blast/boot - 775 sys sys 1100701674 568
+sys/lib/sysconfig/blast/boot - 775 sys sys 1107436263 568
 sys/lib/sysconfig/proto - 20000000775 sys sys 959740591 0
 sys/lib/sysconfig/proto/allproto - 664 sys sys 945018241 2
 sys/lib/sysconfig/proto/armpaqproto - 664 sys sys 1089299189 2230
@@ -5123,7 +5126,7 @@ sys/man/8/nfsserver - 664 sys sys 1017251291 3397
 sys/man/8/pcmcia - 664 sys sys 944959679 408
 sys/man/8/pem - 664 sys sys 1060263669 1189
 sys/man/8/ping - 664 sys sys 1084473185 3436
-sys/man/8/plan9.ini - 664 sys sys 1094650551 20806
+sys/man/8/plan9.ini - 664 sys sys 1107448255 21148
 sys/man/8/pop3 - 664 sys sys 1063854676 2720
 sys/man/8/ppp - 664 sys sys 1096036494 4424
 sys/man/8/prep - 664 sys sys 1079705872 13820
@@ -5273,7 +5276,7 @@ sys/src/9/boot/bootmkfile - 664 sys sys 1091732792 404
 sys/src/9/boot/doauthenticate.c - 664 sys sys 1015012529 2300
 sys/src/9/boot/embed.c - 664 sys sys 1039763720 1191
 sys/src/9/boot/getpasswd.c - 664 sys sys 957373373 654
-sys/src/9/boot/local.c - 664 sys sys 1105976808 5619
+sys/src/9/boot/local.c - 664 sys sys 1107436091 5619
 sys/src/9/boot/mkboot - 775 sys sys 1045504382 1935
 sys/src/9/boot/nopsession.c - 664 sys sys 957373374 843
 sys/src/9/boot/paq.c - 664 sys sys 1067722601 1099
@@ -5391,7 +5394,7 @@ sys/src/9/pc/ethermii.h - 664 sys sys 1086873891 3258
 sys/src/9/pc/etherrhine.c - 664 sys sys 1081706478 13799
 sys/src/9/pc/ethersink.c - 664 sys sys 1048644103 1076
 sys/src/9/pc/ethersmc.c - 664 sys sys 1071245461 15103
-sys/src/9/pc/etherwavelan.c - 664 sys sys 1026847642 3722
+sys/src/9/pc/etherwavelan.c - 664 sys sys 1107448246 3723
 sys/src/9/pc/floppy.h - 664 sys sys 1055700609 3835
 sys/src/9/pc/fns.h - 664 sys sys 1089046996 4372
 sys/src/9/pc/hcwAMC.h - 664 sys sys 1026860163 166004
@@ -5420,7 +5423,7 @@ sys/src/9/pc/pcdisk - 664 sys sys 1073851851 1427
 sys/src/9/pc/pcf - 664 sys sys 1104430623 1485
 sys/src/9/pc/pcfl - 664 sys sys 1042004821 1563
 sys/src/9/pc/pcflop - 664 sys sys 1104430611 1438
-sys/src/9/pc/pci.c - 664 sys sys 1096379063 25817
+sys/src/9/pc/pci.c - 664 sys sys 1107436009 25850
 sys/src/9/pc/pcmciamodem.c - 664 sys sys 1099761153 1586
 sys/src/9/pc/piix4smbus.c - 664 sys sys 1091129037 5230
 sys/src/9/pc/plan9l.s - 664 sys sys 1015014521 910
@@ -5434,7 +5437,7 @@ sys/src/9/pc/screen.h - 664 sys sys 1060267144 3797
 sys/src/9/pc/sd53c8xx.c - 664 sys sys 1086987325 52219
 sys/src/9/pc/sd53c8xx.i - 664 sys sys 1045063730 27355
 sys/src/9/pc/sd53c8xx.n - 664 sys sys 1032059019 12455
-sys/src/9/pc/sdata.c - 664 sys sys 1099487462 50970
+sys/src/9/pc/sdata.c - 664 sys sys 1107436009 51019
 sys/src/9/pc/sdmylex.c - 664 sys sys 1071245460 27812
 sys/src/9/pc/sdscsi.c - 664 sys sys 1077033661 7487
 sys/src/9/pc/trap.c - 664 sys sys 1105109602 20537
@@ -5466,8 +5469,8 @@ sys/src/9/pc/vgatvp3020.c - 664 sys sys 1015014528 4491
 sys/src/9/pc/vgatvp3026.c - 664 sys sys 1015014528 3940
 sys/src/9/pc/vgavmware.c - 664 sys sys 1063858321 6398
 sys/src/9/pc/vgax.c - 664 sys sys 1015014528 1655
-sys/src/9/pc/wavelan.c - 664 sys sys 1056299581 27253
-sys/src/9/pc/wavelan.h - 664 sys sys 1055700615 6151
+sys/src/9/pc/wavelan.c - 664 sys sys 1107448246 27838
+sys/src/9/pc/wavelan.h - 664 sys sys 1107448246 6169
 sys/src/9/port - 20000000775 sys sys 1018469625 0
 sys/src/9/port/alarm.c - 664 sys sys 1067722766 1426
 sys/src/9/port/alloc.c - 664 sys sys 1102093389 5645
@@ -5555,7 +5558,7 @@ sys/src/9/port/tod.c - 664 sys sys 1067722762 4856
 sys/src/9/port/unthwack.c - 664 sys sys 1057323394 5249
 sys/src/9/port/xalloc.c - 664 sys sys 1097074047 4030
 sys/src/9/ppc - 20000000775 sys sys 1059490838 0
-sys/src/9/ppc/blast - 664 sys sys 1100701674 685
+sys/src/9/ppc/blast - 664 sys sys 1107436310 670
 sys/src/9/ppc/blast.h - 664 sys sys 1059490750 3109
 sys/src/9/ppc/clock.c - 664 sys sys 1100701675 1036
 sys/src/9/ppc/dat.h - 664 sys sys 1097073353 4712
@@ -7058,11 +7061,17 @@ sys/src/cmd/aux/flashfs/mkit - 775 sys sys 1015009082 86
 sys/src/cmd/aux/flashfs/request.c - 664 sys sys 1019507619 5739
 sys/src/cmd/aux/flashfs/testld.c - 664 sys sys 1015009082 1043
 sys/src/cmd/aux/flashfs/utils.c - 664 sys sys 1019498850 1097
+sys/src/cmd/aux/gps - 20000000775 sys sys 1107448949 0
+sys/src/cmd/aux/gps/dat.h - 664 sys sys 1107448949 287
+sys/src/cmd/aux/gps/gpsevermore.c - 664 sys sys 1107448815 4501
+sys/src/cmd/aux/gps/gpsfs.c - 664 sys sys 1107448815 16152
+sys/src/cmd/aux/gps/mkfile - 664 sys sys 1107448949 234
+sys/src/cmd/aux/gps/util.c - 664 sys sys 1107448815 2795
 sys/src/cmd/aux/lines.c - 664 sys sys 1015008782 546
 sys/src/cmd/aux/lis - 775 sys sys 944960794 45
 sys/src/cmd/aux/listen.c - 664 sys sys 1093452954 8142
 sys/src/cmd/aux/listen1.c - 664 sys sys 1093452955 2018
-sys/src/cmd/aux/mkfile - 664 sys sys 1105123164 962
+sys/src/cmd/aux/mkfile - 664 sys sys 1107448969 968
 sys/src/cmd/aux/mklatinkbd.c - 664 sys sys 953253425 3813
 sys/src/cmd/aux/mnihongo - 20000000775 sys sys 944960789 0
 sys/src/cmd/aux/mnihongo/README - 664 sys sys 944960789 475
@@ -7085,7 +7094,7 @@ sys/src/cmd/aux/rdwr.c - 664 sys sys 1016833876 811
 sys/src/cmd/aux/reboot.c - 664 sys sys 1014925091 1411
 sys/src/cmd/aux/searchfs.c - 664 sys sys 1014925091 18176
 sys/src/cmd/aux/stub.c - 664 sys sys 1098196222 2723
-sys/src/cmd/aux/timesync.c - 664 sys sys 1083697436 24772
+sys/src/cmd/aux/timesync.c - 664 sys sys 1107448970 25758
 sys/src/cmd/aux/trampoline.c - 664 sys sys 1078840013 3521
 sys/src/cmd/aux/typepasswd.c - 664 sys sys 1014925091 1761
 sys/src/cmd/aux/unlock - 664 sys sys 944960793 0
@@ -10802,6 +10811,7 @@ sys/src/cmd/unix/u9fs/utfrune.c - 664 sys sys 1015092354 387
 sys/src/cmd/unix/winplumb.c - 664 sys sys 1047233509 5015
 sys/src/cmd/unix/winplumb.exe - 664 sys sys 1047233509 32768
 sys/src/cmd/unix/winstart - 775 sys sys 1047233540 60
+sys/src/cmd/unlnfs.c - 664 sys sys 1107435471 1949
 sys/src/cmd/unmount.c - 664 sys sys 1014926615 442
 sys/src/cmd/upas - 20000000775 sys sys 1018549518 0
 sys/src/cmd/upas/README - 664 sys sys 944961329 1041
@@ -10859,7 +10869,7 @@ sys/src/cmd/upas/fs/readdir.c - 664 sys sys 944961331 203
 sys/src/cmd/upas/fs/strtotm.c - 664 sys sys 1041137528 1904
 sys/src/cmd/upas/fs/tester.c - 664 sys sys 985037420 1418
 sys/src/cmd/upas/marshal - 20000000775 sys sys 1015009721 0
-sys/src/cmd/upas/marshal/marshal.c - 664 sys sys 1089299189 32566
+sys/src/cmd/upas/marshal/marshal.c - 664 sys sys 1107435333 32664
 sys/src/cmd/upas/marshal/mkfile - 664 sys sys 1047490298 235
 sys/src/cmd/upas/misc - 20000000775 sys sys 944961318 0
 sys/src/cmd/upas/misc/gone.fishing - 664 sys sys 944961318 313
@@ -11344,12 +11354,12 @@ sys/src/games/music/mkfile - 664 sys sys 1103793915 723
 sys/src/games/music/mkinc - 664 sys sys 1103793915 92
 sys/src/games/music/playlistfs - 20000000775 sys sys 1103794221 0
 sys/src/games/music/playlistfs/boilerplate.c - 664 sys sys 1105531426 1362
-sys/src/games/music/playlistfs/fs.c - 664 sys sys 1103793922 18071
+sys/src/games/music/playlistfs/fs.c - 664 sys sys 1107436434 17485
 sys/src/games/music/playlistfs/main.c - 664 sys sys 1103793922 1636
 sys/src/games/music/playlistfs/mk.dep - 664 sys sys 1103793923 594
 sys/src/games/music/playlistfs/mkfile - 664 sys sys 1103793923 187
 sys/src/games/music/playlistfs/player.c - 664 sys sys 1103793923 10228
-sys/src/games/music/playlistfs/playlist.h - 664 sys sys 1103793923 2608
+sys/src/games/music/playlistfs/playlist.h - 664 sys sys 1107436453 2579
 sys/src/games/music/playlistfs/playplumb.c - 664 sys sys 1103793924 280
 sys/src/games/music/playlistfs/volume.c - 664 sys sys 1103793924 2065
 sys/src/games/music/readcd - 775 sys sys 1103793915 996

+ 37 - 0
dist/replica/plan9.log

@@ -13373,3 +13373,40 @@
 1107405018 0 c 386/bin/8c - 775 sys sys 1107403546 357746
 1107405018 1 c 386/bin/auth/login - 775 sys sys 1107403546 103379
 1107405018 2 c 386/bin/upas/fs - 775 sys sys 1107403547 332387
+1107406819 0 c 386/9pc - 775 sys sys 1107405606 1833830
+1107406819 1 c 386/9pccpu - 775 sys sys 1107405611 1488772
+1107406819 2 c 386/9pcdisk - 775 sys sys 1107405618 2039532
+1107406819 3 c 386/9pcf - 775 sys sys 1107405626 2382364
+1107406819 4 c 386/bin/8c - 775 sys sys 1107405596 357746
+1107406819 5 c 386/bin/auth/login - 775 sys sys 1107405597 103379
+1107406819 6 c 386/bin/upas/fs - 775 sys sys 1107405598 332387
+1107435625 0 a sys/src/cmd/unlnfs.c - 664 sys sys 1107435471 1949
+1107435625 1 c sys/src/cmd/upas/marshal/marshal.c - 664 sys sys 1107435333 32664
+1107437425 0 c sys/lib/sysconfig/blast/boot - 775 sys sys 1107436263 568
+1107437425 1 c sys/src/9/boot/local.c - 664 sys sys 1107436091 5619
+1107437425 2 c sys/src/9/pc/pci.c - 664 sys sys 1107436009 25850
+1107437425 3 c sys/src/9/pc/sdata.c - 664 sys sys 1107436009 51019
+1107437425 4 c sys/src/9/ppc/blast - 664 sys sys 1107436310 670
+1107437425 5 c sys/src/games/music/playlistfs/fs.c - 664 sys sys 1107436434 17485
+1107437425 6 c sys/src/games/music/playlistfs/playlist.h - 664 sys sys 1107436453 2579
+1107448227 0 c sys/man/8/plan9.ini - 664 sys sys 1107448255 21148
+1107448227 1 c sys/src/9/pc/etherwavelan.c - 664 sys sys 1107448246 3723
+1107448227 2 c sys/src/9/pc/wavelan.c - 664 sys sys 1107448246 27838
+1107448227 3 c sys/src/9/pc/wavelan.h - 664 sys sys 1107448246 6169
+1107450028 0 a sys/src/cmd/aux/gps - 20000000775 sys sys 1107448949 0
+1107450028 1 a sys/src/cmd/aux/gps/dat.h - 664 sys sys 1107448949 287
+1107450028 2 a sys/src/cmd/aux/gps/gpsevermore.c - 664 sys sys 1107448815 4501
+1107450028 3 a sys/src/cmd/aux/gps/gpsfs.c - 664 sys sys 1107448815 16152
+1107450028 4 a sys/src/cmd/aux/gps/mkfile - 664 sys sys 1107448949 234
+1107450028 5 a sys/src/cmd/aux/gps/util.c - 664 sys sys 1107448815 2795
+1107450028 6 c sys/src/cmd/aux/mkfile - 664 sys sys 1107448969 968
+1107450028 7 c sys/src/cmd/aux/timesync.c - 664 sys sys 1107448970 25758
+1107491437 0 c 386/9pc - 775 sys sys 1107490489 1834244
+1107491437 1 c 386/9pccpu - 775 sys sys 1107490494 1488803
+1107491437 2 c 386/9pcdisk - 775 sys sys 1107490498 2039946
+1107491437 3 c 386/9pcf - 775 sys sys 1107490504 2382778
+1107491437 4 a 386/bin/aux/gpsevermore - 775 sys sys 1107490157 71417
+1107491437 5 a 386/bin/aux/gpsfs - 775 sys sys 1107490157 174347
+1107491437 6 c 386/bin/aux/timesync - 775 sys sys 1107490157 128213
+1107491437 7 a 386/bin/unlnfs - 775 sys sys 1107490157 71362
+1107491437 8 c 386/bin/upas/marshal - 775 sys sys 1107490159 132595

+ 2 - 2
sys/lib/sysconfig/blast/boot

@@ -17,8 +17,8 @@ fsaddr=`{sed -n 's/	fs=(.*)/\1/p' /net/ndb|sed 1q}
 
 factotum -sfactotum -S -a $authaddr
 
-if(! srv il!$fsaddr!17008 boot){
-	if(! srv tcp!$fsaddr!564 boot)
+if(! srv tcp!$fsaddr!564 boot){
+	if(! srv il!$fsaddr!17008 boot)
 		exec ./rc -m/boot/rcmain -i
 }
 

+ 14 - 5
sys/man/8/plan9.ini

@@ -259,14 +259,23 @@ and defaults to
 	key\fIN\fP=string
 .EE
 sets the encryption key
-.I n
+.I N
 (where
-.I n
+.I N
 is in the range 1 to 4 inclusive) to
 .IR string ;
 this will also set the transmit key to
-.I n
+.I N
 (see below).
+There are two formats for
+.I string
+which depend on the length of the string.
+If it is exactly 5 or 13 characters long it is assumed
+to be an alphanumeric key; if it is exactly 10 or 26 characters
+long the key is assumed to be in hex format (without a leading
+.IR 0x ).
+The lengths are checked,
+as is the format of a hex key.
 .EX
 	txkey=number
 .EE
@@ -283,14 +292,14 @@ The defaults are intended to match the common case of
 a managed network with encryption and a typical entry would 
 only require, for example
 .EX
-	essid=left-armpit key2=fishcalledraawaru
+	essid=left-armpit key1=afish key2=calledraawaru
 .EE
 if the port and IRQ defaults are used.
 These options may be set after boot by writing to the device's
 .I ctl
 file using a space as the separator between option and value, e.g.
 .EX
-	echo 'key2 fishcalledraawaru' > /net/ether0/0/ctl
+	echo 'key2 1d8f65c9a52d83c8e4b43f94af' > /net/ether0/0/ctl
 .EE
 .TP
 .B wavelanpci

+ 1 - 1
sys/src/9/boot/local.c

@@ -237,7 +237,7 @@ connectlocalfossil(void)
 			 * If the announce address is tcp!*!foo, then set
 			 * $venti to tcp!127.1!foo instead, which is actually dialable.
 			 */
-			if((p = strstr(f[1], "!*!")) == 0){
+			if((p = strstr(f[1], "!*!")) != 0){
 				*p = 0;
 				snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
 				f[1] = buf;

+ 1 - 1
sys/src/9/pc/etherwavelan.c

@@ -45,7 +45,7 @@ wavelanpcmciareset(Ether *ether)
 	for(i=0; i<ether->nopt; i++){
 		if(cistrncmp(ether->opt[i], "id=", 3) == 0){
 			if((ctlr->slot = pcmspecial(&ether->opt[i][3], ether)) < 0)
-				return -1;
+				goto abort;
 			break;
 		}
 	}

+ 2 - 1
sys/src/9/pc/pci.c

@@ -634,7 +634,8 @@ static Bridge southbridges[] = {
 	{ 0x8086, 0x2420, pIIxget, pIIxset },	// Intel 82801AB
 	{ 0x8086, 0x2440, pIIxget, pIIxset },	// Intel 82801BA
 	{ 0x8086, 0x244c, pIIxget, pIIxset },	// Intel 82801BAM
-	{ 0x8086, 0x24d0, pIIxget, pIIxset },	// Intel ICH5R, as found in 875P chipset
+	{ 0x8086, 0x248c, pIIxget, pIIxset },	// Intel 82801CAM
+	{ 0x8086, 0x24d0, pIIxget, pIIxset },	// Intel 82801EB
 	{ 0x1106, 0x0586, viaget, viaset },	// Viatech 82C586
 	{ 0x1106, 0x0596, viaget, viaset },	// Viatech 82C596
 	{ 0x1106, 0x0686, viaget, viaset },	// Viatech 82C686

+ 1 - 0
sys/src/9/pc/sdata.c

@@ -1926,6 +1926,7 @@ atapnp(void)
 		case (0x24CA<<16)|0x8086:	/* 82801DBM (ICH4, Mobile) */
 		case (0x24CB<<16)|0x8086:	/* 82801DB (ICH4, High-End) */
 		case (0x24DB<<16)|0x8086:	/* 82801EB (ICH5) */
+		case (0x266F<<16)|0x8086:	/* 82801FB (ICH6) */
 			break;
 		}
 

+ 46 - 7
sys/src/9/pc/wavelan.c

@@ -961,12 +961,55 @@ w_ifstat(Ether* ether, void* a, long n, ulong offset)
 #undef PRINTSTR
 #undef PRINTSTAT
 
+static int
+parsekey(WKey* key, char* a) 
+{
+	int i, k, len, n;
+	char buf[WMaxKeyLen];
+
+	len = strlen(a);
+	if(len == WMinKeyLen || len == WMaxKeyLen){
+		memset(key->dat, 0, sizeof(key->dat));
+		memmove(key->dat, a, len);
+		key->len = len;
+
+		return 0;
+	}
+	else if(len == WMinKeyLen*2 || len == WMaxKeyLen*2){
+		k = 0;
+		for(i = 0; i < len; i++){
+			if(*a >= '0' && *a <= '9')
+				n = *a++ - '0';
+			else if(*a >= 'a' && *a <= 'f')
+				n = *a++ - 'a' + 10;
+			else if(*a >= 'A' && *a <= 'F')
+				n = *a++ - 'A' + 10;
+			else
+				return -1;
+	
+			if(i & 1){
+				buf[k] |= n;
+				k++;
+			}
+			else
+				buf[k] = n<<4;
+		}
+
+		memset(key->dat, 0, sizeof(key->dat));
+		memmove(key->dat, buf, k);
+		key->len = k;
+
+		return 0;
+	}
+
+	return -1;
+}
+
 int
 w_option(Ctlr* ctlr, char* buf, long n)
 {
 	char *p;
 	int i, r;
-	WKey *key;
 	Cmdbuf *cb;
 
 	r = 0;
@@ -1035,12 +1078,8 @@ w_option(Ctlr* ctlr, char* buf, long n)
 	else if(cistrncmp(cb->f[0], "key", 3) == 0){
 		if((i = atoi(cb->f[0]+3)) >= 1 && i <= WNKeys){
 			ctlr->txkey = i-1;
-			key = &ctlr->keys.keys[ctlr->txkey];
-			key->len = strlen(cb->f[1]);
-			if(key->len > WKeyLen)
-				key->len = WKeyLen;
-			memset(key->dat, 0, sizeof(key->dat));
-			memmove(key->dat, cb->f[1], key->len);
+			if(parsekey(&ctlr->keys.keys[ctlr->txkey], cb->f[1]))
+				r = -1;
 		}
 		else
 			r = -1;

+ 1 - 0
sys/src/9/pc/wavelan.h

@@ -63,6 +63,7 @@ enum
 	WNKeys		= 4,
 	WKeyLen		= 14,
 	WMinKeyLen	= 5,
+	WMaxKeyLen	= 13,
 
 	// Wavelan hermes registers
 	WR_Cmd		= 0x00,

+ 0 - 1
sys/src/9/ppc/blast

@@ -57,6 +57,5 @@ bootdir
 	/power/bin/ip/ipconfig
 	/power/bin/auth/factotum
 	/power/bin/ls
-	/power/bin/ps
 	/power/bin/auth/wrkey
 	/sys/lib/sysconfig/blast/boot

+ 19 - 0
sys/src/cmd/aux/gps/dat.h

@@ -0,0 +1,19 @@
+typedef struct Place Place;
+
+struct Place {
+	double	lon;
+	double 	lat;
+};
+#pragma	varargck	type	"L"	Place
+
+enum {
+	Undef		= 0x80000000,
+	Baud=		4800,
+};
+
+extern Place nowhere;
+extern int debug;
+
+int placeconv(Fmt*);
+Place strtopos(char*, char**);
+int strtolatlon(char*, char**, Place*);

+ 224 - 0
sys/src/cmd/aux/gps/gpsevermore.c

@@ -0,0 +1,224 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+
+char *serial = "/dev/eia0";
+
+int ttyfd, ctlfd, debug;
+int baud = Baud;
+char *baudstr = "b%dd1r1pns1l8i1w5";
+
+Place where = {-(74.0 + 23.9191/60.0), 40.0 + 41.1346/60.0};
+
+void	setline(void);
+void	evermore80(Place, int);
+void	evermore89(int);
+void	evermore8e(void);
+
+void
+setline(void){
+	char *serialctl;
+
+	serialctl = smprint("%sctl", serial);
+	if((ttyfd = open(serial, ORDWR)) < 0)
+		sysfatal("%s: %r", serial);
+	if((ctlfd = open(serialctl, OWRITE)) >= 0){
+		if(fprint(ctlfd, baudstr, baud) < 0)
+			sysfatal("%s: %r", serialctl);
+	}
+	free(serialctl);
+}
+
+enum {
+	GGAon = 0x01,
+	GLLon = 0x02,
+	GSAon = 0x04,
+	GSVon = 0x08,
+	RMCon = 0x10,
+	VTGon = 0x20,
+	CRCon = 0x40,
+	EMTon = 0x80
+};
+
+char*
+putbyte(char *s, int v)
+{
+	*s++ = v;
+	if((v & 0xff) == 0x10)
+		*s++ = v;
+	return s;
+}
+
+char*
+putshort(char *s, int v)
+{
+	s = putbyte(s, v);
+	s = putbyte(s, v >> 8);
+	return s;
+}
+
+char*
+putlong(char *s, long v)
+{
+	s = putbyte(s, v);
+	s = putbyte(s, v >> 8);
+	s = putbyte(s, v >> 16);
+	s = putbyte(s, v >> 24);
+	return s;
+}
+
+void
+evermoresend(char *body, int l)
+{
+	char buf[8], *s;
+	int crc, i;
+
+	s = buf;
+	*s++ = 0x10;			/* DCE */
+	*s++ = 0x02;			/* STX */
+	s = putbyte(s, l);		/* length */
+	write(ttyfd, buf, s-buf);	/* write header */
+
+	write(ttyfd, body, l);		/* write body */
+
+	crc = 0;
+	for(i = 0; i < l; i++)
+		crc += body[i];		/* calculate crc */
+	s = buf;
+	s = putbyte(s, crc);		/* checksum */
+	*s++ = 0x10;			/* DCE */
+	*s++ = 0x03;			/* ETX */
+	write(ttyfd, buf, s-buf);	/* write trailer */
+}
+
+void
+evermore80(Place pl, int baud)
+{
+	char buf[32], *s;
+	long now, seconds, week;
+
+	fprint(2, "Evermore80");
+
+	time(&now);
+	seconds = now - 315964800;
+	week = (seconds / (7*24*3600));
+	seconds = seconds %  (7*24*3600);
+	s = buf;
+
+	s = putbyte(s, 0x80);		/* message ID */
+	s = putshort(s, week);		/* week number */
+	s = putlong(s, seconds*100);	/* seconds */
+	s = putshort(s, pl.lat*10.0);	/* latitude tenths degree */
+	s = putshort(s, pl.lon*10.0);	/* longitude tenths degree */
+	s = putshort(s, 100);		/* altitude meters */
+	s = putshort(s, 0);		/* datumn ID */
+	s = putbyte(s, 2);		/* warm start */
+	s = putbyte(s, GGAon|GSAon|GSVon|RMCon|CRCon);
+	switch(baud){
+	case 4800:	s = putbyte(s, 0);	break;
+	case 9600:	s = putbyte(s, 1);	break;
+	case 19200:	s = putbyte(s, 2);	break;
+	case 38400:	s = putbyte(s, 3);	break;
+	default:
+		sysfatal("Illegal baud rate");
+	}
+
+	evermoresend(buf, s - buf);
+	fprint(2, "\n");
+}
+
+void
+evermore89(int baud)
+{
+	char buf[32], *s;
+
+	fprint(2, "Evermore89");
+	s = buf;
+	s = putbyte(s, 0x89);		/* message ID */
+	s = putbyte(s, 0x01);		/* set main serial port */
+	switch(baud){
+	case  4800:	s = putbyte(s, 0x00);	break;
+	case  9600:	s = putbyte(s, 0x01);	break;
+	case 19200:	s = putbyte(s, 0x02);	break;
+	case 38400:	s = putbyte(s, 0x03);	break;
+	default:
+		sysfatal("illegal baud rate %d\n", baud);
+	}
+
+	evermoresend(buf, s - buf);
+	fprint(2, "\n");
+}
+
+void
+evermore8e(void)
+{
+	char buf[32], *s;
+
+	fprint(2, "Evermore8e");
+	s = buf;
+	s = putbyte(s, 0x8e);		/* message ID */
+	s = putbyte(s, GGAon|GSAon|GSVon|RMCon);		/* all messages except GLL and VTG */
+	s = putbyte(s, 0x01);		/* checksum on */
+	s = putbyte(s, 0x01);		/* GGA update rate */
+	s = putbyte(s, 0x0b);		/* GLL update rate */
+	s = putbyte(s, 0x0a);		/* GSA update rate */
+	s = putbyte(s, 0x14);		/* GSV update rate */
+	s = putbyte(s, 0x08);		/* RMC update rate */
+	s = putbyte(s, 0x0d);		/* VTG update rate */
+
+	evermoresend(buf, s - buf);
+	fprint(2, "\n");
+}
+
+void
+main(int argc, char*argv[])
+{
+	char *p;
+	Place pl;
+	int newbaud;
+
+	newbaud = -1;
+	pl = nowhere;
+	ARGBEGIN {
+	default:
+		fprint(2, "usage: %s [-b baud] [-d device] [-l longitude latitude] [-n newbaud]\n", argv0);
+		exits("usage");
+	case 'D':
+		debug++;
+		break;
+	case 'b':
+		baud = strtol(ARGF(), nil, 0);
+		break;
+	case 'd':
+		serial = ARGF();
+		break;
+	case 'l':
+		p = ARGF();
+		if(strtolatlon(p, &p, &pl) < 0)
+			sysfatal("bad position");
+		while(*p == ' ' || *p == '\t' || *p == '\n')
+			p++;
+		if(*p == '\0')
+			p = ARGF();
+		if (strtolatlon(p, &p, &pl) < 0)
+			sysfatal("bad position");
+		while(*p == ' ' || *p == '\t' || *p == '\n')
+			p++;
+		if(*p != '\0')
+			sysfatal("trailing gunk in position");
+		where = pl;
+		break;
+	case 'n':
+		newbaud = strtol(ARGF(), nil, 0);
+		break;
+	} ARGEND
+
+	if(newbaud < 0)
+		newbaud = baud;
+
+	fmtinstall('L', placeconv);
+	print("Initializing GPS to %d baud, at %L, time %s\n",
+		newbaud, where, ctime(time(nil)));
+	setline();
+	evermore80(where, newbaud);
+}

+ 856 - 0
sys/src/cmd/aux/gps/gpsfs.c

@@ -0,0 +1,856 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <ctype.h>
+#include <9p.h>
+#include "dat.h"
+
+enum
+{
+	Numsize=	12,
+	Vlnumsize=	22,
+	Rawbuf=		0x10000,
+	Rawmask=	Rawbuf-1,
+};
+
+#define	nsecperchar	((int)(1000000000.0 * 10.0 / baud))
+
+typedef struct Fix Fix;
+typedef struct Satellite Satellite;
+typedef struct GPSfile GPSfile;
+typedef struct Gpsmsg Gpsmsg;
+
+struct Satellite {
+	int		prn;
+	int		elevation;
+	int		azimuth;
+	int		snr;
+};
+
+struct Fix {
+	int		messages;	/* bitmap of types seen */
+	Place;
+	/*
+	 * The following are in Plan 9 time format:
+	 * seconds or nanoseconds since the epoch.
+	 */
+	vlong		localtime;	/* nsec() value when first byte was read */
+	vlong		gpstime;	/* nsec() value from GPS */
+	long		time;		/* time() value from GPS */
+
+	double		zulu;
+	int		date;
+	char		valid;
+	uchar		quality;
+	ushort		satellites;
+	double		pdop;
+	double		hdop;
+	double		vdop;
+	double		altitude;
+	double		sealevel;
+	double		groundspeed;
+	double		kmh;
+	double		course;
+	double		heading;
+	double		magvar;
+	Satellite	s[12];
+};
+
+struct GPSfile {
+	char	*name;
+	char*	(*rread)(Req*);
+	int	mode;
+	vlong	offset;		/* for raw: rawout - read-offset */
+};
+
+enum {
+	ASTRAL,
+	GPGGA,
+	GPGLL,
+	GPGSA,
+	GPGSV,
+	GPRMC,
+	GPVTG,
+	PRWIRID,
+	PRWIZCH
+};
+
+struct Gpsmsg {
+	char *name;
+	int tokens;
+	ulong errors;
+};
+
+char	raw[Rawbuf];
+vlong	rawin;
+vlong	rawout;
+
+ulong histo[32];
+
+char *serial = "/dev/eia0";
+
+Gpsmsg gpsmsg[] = {
+[ASTRAL]	= { "ASTRAL",	 0,	0},
+[GPGGA]		= { "$GPGGA",	15,	0},
+[GPGLL]		= { "$GPGLL",	 7,	0},
+[GPGSA]		= { "$GPGSA",	18,	0},
+[GPGSV]		= { "$GPGSV",	0,	0},
+[GPRMC]		= { "$GPRMC",	0,	0},
+[GPVTG]		= { "$GPVTG",	0,	0},
+[PRWIRID]	= { "$PRWIRID",	0,	0},
+[PRWIZCH]	= { "$PRWIZCH",	0,	0},
+};
+
+int ttyfd, ctlfd, debug;
+int setrtc;
+int baud = Baud;
+char *baudstr = "b%dd1r1pns1l8i9w5";
+ulong seconds;
+ulong starttime;
+ulong checksumerrors;
+int gpsplayback;	/* If set, return times and positions with `invalid' marker set */
+
+Place where = {-(74.0 + 23.9191/60.0), 40.0 + 41.1346/60.0};
+
+Fix curfix;
+Lock fixlock;
+
+int	type(char*);
+void	setline(void);
+int	getonechar(vlong*);
+void	getline(char*, int, vlong*);
+void	putline(char*);
+void	gettime(Fix*);
+int	getzulu(char *, Fix*);
+int	getalt(char*, char*, Fix*);
+int	getsea(char*, char*, Fix*);
+int	getlat(char*, char*, Fix*);
+int	getlon(char*, char*, Fix*);
+int	getgs(char*, Fix *);
+int	getkmh(char*, Fix*);
+int	getcrs(char*, Fix*);
+int	gethdg(char*, Fix*);
+int	getdate(char*, Fix*);
+int	getmagvar(char*, char*, Fix*);
+void	printfix(int, Fix*);
+void	ropen(Req *r);
+void	rread(Req *r);
+void	rend(Srv *s);
+void	gpsinit(void);
+char*	readposn(Req*);
+char*	readtime(Req*);
+char*	readsats(Req*);
+char*	readstats(Req*);
+char*	readraw(Req*);
+
+GPSfile files[] = {
+	{ "time",	readtime,	0444,	0 },
+	{ "position",	readposn,	0444,	0 },
+	{ "satellites",	readsats,	0444,	0 },
+	{ "stats",	readstats,	0444,	0 },
+	{ "raw",	readraw,	DMEXCL|0444, 0 },
+};
+
+Srv s = {
+	.open	= ropen,
+	.read	= rread,
+
+	.end = rend,
+};
+
+File *root;
+File *gpsdir;
+
+void
+rend(Srv *)
+{
+	sysfatal("gpsfs demised");
+}
+
+void
+ropen(Req *r)
+{
+	respond(r, nil);
+}
+
+void
+rread(Req *r)
+{
+	GPSfile *f;
+
+	r->ofcall.count = 0;
+	f = r->fid->file->aux;
+	respond(r, f->rread(r));
+}
+
+void
+fsinit(void)
+{
+	char* user;
+	int i;
+
+	user = getuser();
+	s.tree = alloctree(user, user, 0555, nil);
+	if(s.tree == nil)
+		sysfatal("fsinit: alloctree: %r");
+	root = s.tree->root;
+	if((gpsdir = createfile(root, "gps", user, DMDIR|0555, nil)) == nil)
+		sysfatal("fsinit: createfile: gps: %r");
+	for(i = 0; i < nelem(files); i++)
+		if(createfile(gpsdir, files[i].name, user, files[i].mode, files + i) == nil)
+			sysfatal("fsinit: createfile: %s: %r", files[i].name);
+}
+
+void
+threadmain(int argc, char*argv[])
+{
+	char *srvname, *mntpt;
+
+	srvname = "gps";
+	mntpt = "/mnt";
+
+	ARGBEGIN {
+	default:
+		fprint(2, "usage: %s [-b baud] [-d device] [-l logfile] [-m mntpt] [-r] [-s postname]\n", argv0);
+		exits("usage");
+	case 'D':
+		debug++;
+		break;
+	case 'b':
+		baud = strtol(ARGF(), nil, 0);
+		break;
+	case 'd':
+		serial = ARGF();
+		break;
+	case 'r':
+		setrtc = 1;
+		break;
+	case 's':
+		srvname = ARGF();
+		break;
+	case 'm':
+		mntpt = ARGF();
+		break;
+	} ARGEND
+
+	fmtinstall('L', placeconv);
+	
+	rfork(RFNOTEG);
+
+	fsinit();
+	gpsinit();
+	threadpostmountsrv(&s, srvname, mntpt, MBEFORE);
+	threadexits(nil);
+}
+
+static void
+gpstrack(void *)
+{
+	Fix fix;
+	static char buf[256], *t[32];
+	int n, i, k, tp;
+	vlong localtime;
+
+	setline();
+	fix.messages = 0;
+	fix.lon = 0;
+	fix.lat = 0;
+	fix.zulu = 0;
+	fix.date = 0;
+	fix.valid = 0;
+	fix.quality = 0;
+	fix.satellites = 0;
+	fix.pdop = 0.0;
+	fix.hdop = 0.0;
+	fix.vdop = 0.0;
+	fix.altitude = 0.0;
+	fix.sealevel = 0.0;
+	fix.groundspeed = 0.0;
+	fix.kmh = 0.0;
+	fix.course = 0.0;
+	fix.heading = 0.0;
+	fix.magvar = 0.0;
+	for(;;){
+		getline(buf, sizeof buf, &localtime);
+		n = getfields(buf, t, nelem(t), 0,",\r\n");
+		if(n == 0)
+			continue;
+		tp = type(t[0]);
+		fix.messages |= 1 << tp;
+		if(tp >= 0 && tp < nelem(gpsmsg) && gpsmsg[tp].tokens && gpsmsg[tp].tokens != n){
+			gpsmsg[tp].errors++;
+			if(debug)
+				fprint(2, "%s: Expect %d tokens, got %d\n",
+					gpsmsg[tp].name, gpsmsg[tp].tokens, n);
+			continue;
+		}
+		switch(tp){
+		case ASTRAL:
+			putline("$IIGPQ,ASTRAL*73");
+			putline("$PRWIILOG,GGA,A,T,10,0");
+			putline("$PRWIILOG,RMC,A,T,10,0");
+			putline("$PRWIILOG,GSA,A,T,10,0");
+			putline("$PRWIILOG,GSV,V,,,");
+			fprint(2, "Reply: %s\n", "$IIGPQ,ASTRAL*73");
+			break;
+		case PRWIRID:
+		case PRWIZCH:
+			for(i = 0; i < n; i++) fprint(2, "%s,", t[i]);
+			fprint(2, "(%d tokens)\n", n);
+			break;
+		case GPGGA:
+			fix.localtime = localtime;
+			fix.quality = strtol(t[6], nil, 10);
+			getzulu(t[1], &fix);
+			getlat(t[2], t[3], &fix);
+			getlon(t[4], t[5], &fix);
+			if(isdigit(*t[7]))
+				fix.satellites = strtol(t[7], nil, 10);
+			if(isdigit(*t[8]))
+				fix.hdop = strtod(t[8], nil);
+			getalt(t[9], t[10], &fix);
+			getsea(t[11], t[12], &fix);
+			if(fix.date)
+				gettime(&fix);
+			break;
+		case GPRMC:
+			fix.valid = *t[2];
+			getgs(t[7], &fix);
+			getcrs(t[8], &fix);
+			getdate(t[9], &fix);
+			getmagvar(t[10], t[11], &fix);
+			if((fix.messages & (1 << GPGGA)) == 0){
+				fix.localtime = localtime;
+				getzulu(t[1], &fix);
+				getlat(t[3], t[4], &fix);
+				getlon(t[5], t[6], &fix);
+				if(fix.date)
+					gettime(&fix);
+			}
+			break;
+		case GPGSA:
+			if(*t[15]) fix.pdop = strtod(t[15], nil);
+			if(*t[16]) fix.hdop = strtod(t[16], nil);
+			if(*t[17]) fix.vdop = strtod(t[17], nil);
+			break;
+		case GPGLL:
+			getlat(t[1], t[2], &fix);
+			getlon(t[3], t[4], &fix);
+			getzulu(t[5], &fix);
+			break;
+		case GPGSV:
+			if(n < 8){
+				gpsmsg[tp].errors++;
+				if(debug)
+					fprint(2, "%s: Expect at least 8 tokens, got %d\n",
+						gpsmsg[tp].name, n);
+				break;
+			}
+			i = 4*(strtol(t[2], nil, 10)-1);	/* starting entry in satellite table */
+			fix.satellites = strtol(t[3], nil, 10);
+			k = 4;
+			while(i < nelem(fix.s) && k + 3 < n){
+				fix.s[i].prn = strtol(t[k++], nil, 10);
+				fix.s[i].elevation = strtol(t[k++], nil, 10);
+				fix.s[i].azimuth = strtol(t[k++], nil, 10);
+				fix.s[i].snr = strtol(t[k++], nil, 10);
+				k += 4;
+				i++;
+			} 
+		case GPVTG:
+			if(n < 8){
+				gpsmsg[tp].errors++;
+				if(debug)
+					fprint(2, "%s: Expect at least 8 tokens, got %d\n",
+						gpsmsg[tp].name, n);
+				break;
+			}
+			getcrs(t[2], &fix);
+			gethdg(t[4], &fix);
+			getgs(t[6], &fix);
+			if(n > 8)
+				getkmh(t[8], &fix);
+			break;
+		default:
+			if(debug && fix.date)
+				fprint(2, "Don't know %s\n", t[0]);
+			break;
+		}
+		if(fix.valid){
+			seconds++;
+			lock(&fixlock);
+			memmove(&curfix, &fix, sizeof fix);
+			unlock(&fixlock);
+			if(debug)
+				printfix(2, &fix);
+			fix.valid = 0;
+			fix.messages = 0;
+			for(i = 0; i < nelem(fix.s); i++)
+				fix.s[i].prn = 0;
+			if(gpsplayback)
+				sleep(100);
+		}
+	}
+}
+
+void
+gpsinit(void)
+{
+	proccreate(gpstrack, nil, 4096);
+}
+
+void
+printfix(int f, Fix *fix){
+	int i;
+
+	fprint(f, "%L, ", fix->Place);
+	fprint(f, "%g, ", fix->magvar);
+	fprint(f, "%gm - %gm = %gm, ", fix->altitude, fix->sealevel, fix->altitude - fix->sealevel);
+	fprint(f, "%06dZ(%g)-", (int)fix->zulu, fix->zulu);
+	fprint(f, "%06d\n", fix->date);
+	if(fix->lat >= 0)
+		fprint(f, "%11.8fN, ", fix->lat);
+	else
+		fprint(f, "%11.8fS, ", -fix->lat);		
+	if(fix->lon >= 0)
+		fprint(f, "%12.8fE, ", fix->lon);
+	else
+		fprint(f, "%12.8fW, ", -fix->lon);
+	fprint(f, "%g@%g, ", fix->course, fix->groundspeed);
+	fprint(f, "(%c, %ds)\n", fix->valid, fix->satellites);
+	for(i = 0; i < nelem(fix->s); i++){
+		if(fix->s[i].prn == 0)
+			continue;
+		fprint(f, "[%d, %d°, %d°, %d]\n",
+			fix->s[i].prn, fix->s[i].elevation, fix->s[i].azimuth, fix->s[i].snr);
+	}
+}
+
+char*
+readposn(Req *r)
+{
+	Fix f;
+	char buf[256];
+
+	lock(&fixlock);
+	memmove(&f, &curfix, sizeof f);
+	unlock(&fixlock);
+	snprint(buf, sizeof buf, "%x	%06dZ	%lud	%g	%g	%g	%g	%g	%g",
+		gpsplayback|f.quality, (int)f.zulu, f.time, f.lon, f.lat, f.altitude - f.sealevel,
+		f.course, f.groundspeed, f.magvar);
+	readstr(r, buf);
+	return nil;
+}
+
+char*
+readtime(Req *r)
+{
+	Fix f;
+	char buf[Numsize+Vlnumsize+Vlnumsize+8];
+
+	lock(&fixlock);
+	memmove(&f, &curfix, sizeof f);
+	unlock(&fixlock);
+	seprint(buf, buf + sizeof buf, "%*.0lud %*.0llud %*.0llud %c",
+		Numsize-1, f.time,
+		Vlnumsize-1, f.gpstime,
+		Vlnumsize-1, f.localtime, f.valid + (gpsplayback?1:0));
+	readstr(r, buf);
+	return nil;
+}
+
+char*
+readstats(Req *r)
+{
+	int i;
+	char buf[1024], *p;
+
+	p = buf;
+	p = seprint(p, buf + sizeof buf, "%lld bytes read, %ld samples processed in %ld seconds\n",
+		rawin, seconds, curfix.time - starttime);
+	p = seprint(p, buf + sizeof buf, "%lud checksum errors\n", checksumerrors);
+	p = seprint(p, buf + sizeof buf, "format errors:");
+	for(i = 0; i < nelem(gpsmsg); i++){
+		p = seprint(p, buf + sizeof buf, "[%s]: %ld, ",
+			gpsmsg[i].name, gpsmsg[i].errors);
+	}
+	p = seprint(p, buf + sizeof buf, "\nhistogram of # bytes received per buffer:\n");
+	for(i = 0; i < nelem(histo); i++){
+		p = seprint(p, buf + sizeof buf, "[%d]: %ld ",
+			i, histo[i]);
+	}
+	seprint(p, buf + sizeof buf, "\n");
+	readstr(r, buf);
+	return nil;
+}
+
+char*
+readsats(Req *r)
+{
+	Fix f;
+	int i;
+	char buf[1024], *p;
+
+	lock(&fixlock);
+	memmove(&f, &curfix, sizeof f);
+	unlock(&fixlock);
+	p = seprint(buf, buf + sizeof buf, "%d	%d\n", gpsplayback|f.quality, f.satellites);
+	for(i = 0; i < nelem(f.s); i++){
+		if(f.s[i].prn == 0)
+			continue;
+		p = seprint(p, buf + sizeof buf, "%d	%d	%d	%d\n",
+			f.s[i].prn, f.s[i].elevation, f.s[i].azimuth, f.s[i].snr);
+	}
+	readstr(r, buf);
+	return nil;
+}
+
+char*
+readraw(Req *r)
+{
+	int n;
+	GPSfile *f;
+
+	f = r->fid->file->aux;
+	if(rawin - rawout > Rawbuf){
+		rawout = rawin - Rawbuf;
+		f->offset = rawout - r->ifcall.offset;
+	}
+	n = Rawbuf - (rawout&Rawmask);
+	if(rawin - rawout < n)
+		n = rawin - rawout;
+	if(r->ifcall.count < n)
+		n = r->ifcall.count;
+	r->ofcall.count = n;
+	if(n > 0){
+		memmove(r->ofcall.data, raw + (rawout & Rawmask), n);
+		rawout += n;
+	}
+	return nil;
+}
+
+void
+rtcset(long t)
+{
+	static int fd;
+	long r;
+	int n;
+	char buf[32];
+
+	if(fd <= 0 && (fd = open("#r/rtc", ORDWR)) < 0){
+		fprint(2, "Can't open #r/rtc: %r\n");
+		return;
+	}
+	n = read(fd, buf, sizeof buf - 1);
+	if(n <= 0){
+		fprint(2, "Can't read #r/rtc: %r\n");
+		return;
+	}
+	buf[n] = '\0';
+	r = strtol(buf, nil, 0);
+	if(r <= 0){
+		fprint(2, "ridiculous #r/rtc: %ld\n", r);
+		return;
+	}
+	if(r - t > 1 || t - r > 0){
+		seek(fd, 0, 0);
+		fprint(fd, "%ld", t);
+		fprint(2, "correcting #r/rtc: %ld → %ld\n", r, t);
+	}
+	seek(fd, 0, 0);
+}
+
+void
+gettime(Fix *f){
+	/* Convert zulu time and date to Plan9 time(2) */
+	Tm tm;
+	int zulu;
+	double d;
+
+	zulu = f->zulu;
+	memset(&tm, 0, sizeof tm );
+	tm.sec = zulu % 100;
+	tm.min = (zulu/100) % 100;
+	tm.hour = zulu / 10000;
+	tm.year = f->date % 100 + 100;	/* This'll only work until 2099 */
+	tm.mon = ((f->date/100) % 100) - 1;
+	tm.mday = f->date / 10000;
+	strcpy(tm.zone, "GMT");
+	f->time = tm2sec(&tm);
+	if(starttime == 0) starttime = f->time;
+	f->gpstime = 1000000000LL * f->time + 1000000 * (int)modf(f->zulu, &d);
+	if(setrtc){
+		if(setrtc == 1 || (f->time % 300) == 0){
+			rtcset(f->time);
+			setrtc++;
+		}
+	}
+}
+
+int
+getzulu(char *s, Fix *f){
+	if(*s == '\0') return 0;
+	if(isdigit(*s)){
+		f->zulu = strtod(s, nil);
+		return 1;
+	}
+	return 0;
+}
+
+int
+getdate(char *s, Fix *f){
+	if(*s == 0) return 0;
+	if(isdigit(*s)){
+		f->date = strtol(s, nil, 10);
+		return 1;
+	}
+	return 0;
+}
+
+int
+getgs(char *s1, Fix *f){
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1)){
+		f->groundspeed = strtod(s1, nil);
+		return 1;
+	}
+	return 0;
+}
+
+int
+getkmh(char *s1, Fix *f){
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1)){
+		f->kmh = strtod(s1, nil);
+		return 1;
+	}
+	return 0;
+}
+
+int
+getcrs(char *s1, Fix *f){
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1)){
+		f->course = strtod(s1, nil);
+		return 1;
+	}
+	return 0;
+}
+
+int
+gethdg(char *s1, Fix *f){
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1)){
+		f->heading = strtod(s1, nil);
+		return 1;
+	}
+	return 0;
+}
+
+int
+getalt(char *s1, char *s2, Fix *f){
+	double alt;
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1)){
+		alt = strtod(s1, nil);
+		if(*s2 == 'M'){
+			f->altitude = alt;
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+int
+getsea(char *s1, char *s2, Fix *f){
+	double alt;
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1)){
+		alt = strtod(s1, nil);
+		if(*s2 == 'M'){
+			f->sealevel = alt;
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+int
+getlat(char *s1, char *s2, Fix *f){
+	double lat;
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1) && strlen(s1) > 5){
+		lat = strtod(s1+2, nil);
+		lat /= 60.0;
+		lat += 10*(s1[0] - '0') + s1[1] - '0';
+		if(*s2 == 'S'){
+			f->lat = -lat;
+			return 1;
+		}
+		if(*s2 == 'N'){
+			f->lat = lat;
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+int
+getlon(char *s1, char *s2, Fix *f){
+	double lon;
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1) && strlen(s1) > 5){
+		lon = 100*(s1[0] - '0') + 10*(s1[1] - '0') + s1[2] - '0' +
+			strtod(s1+3, nil)/60.0;
+		if(*s2 == 'W'){
+			f->lon = -lon;
+			return 1;
+		}
+		if(*s2 == 'E'){
+			f->lon = lon;
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+int
+getmagvar(char *s1, char *s2, Fix *f){
+	double magvar;
+
+	if(*s1 == 0) return 0;
+	if(isdigit(*s1) && strlen(s1) > 5){
+		magvar = 100*(s1[0] - '0') + 10*(s1[1] - '0') + s1[2] - '0' +
+			strtod(s1+3, nil)/60.0;
+		if(*s2 == 'W'){
+			f->magvar = -magvar;
+			return 1;
+		}
+		if(*s2 == 'E'){
+			f->magvar = magvar;
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+void
+putline(char *s){
+	write(ttyfd, s, strlen(s));
+	write(ttyfd, "\r\n", 2);
+}
+
+int
+type(char *s){
+	int i;
+
+	for(i = 0; i < nelem(gpsmsg); i++){
+		if(strcmp(s, gpsmsg[i].name) == 0) return i;
+	}
+	return -1;
+}
+
+void
+setline(void){
+	char *serialctl;
+
+	serialctl = smprint("%sctl", serial);
+	if((ttyfd = open(serial, ORDWR)) < 0)
+		sysfatal("%s: %r", serial);
+	if((ctlfd = open(serialctl, OWRITE)) >= 0){
+		if(fprint(ctlfd, baudstr, baud) < 0)
+			sysfatal("%s: %r", serialctl);
+	}else
+		gpsplayback = 0x8;
+	free(serialctl);
+}
+
+int getonechar(vlong *t){
+	static char buf[32], *p;
+	static int n;
+
+	if(n == 0){
+		n = read(ttyfd, buf, sizeof(buf));
+		if(t) *t = nsec();
+		if(n < 0)
+			sysfatal("%s: %r", serial);
+		if(n == 0)
+			threadexits(nil);
+		/*
+		 * We received n characters, so the first must have been there
+		 * at least n/(10*baud) seconds (10 is 1 start
+		 * bit, one stop bit and 8 data bits per character)
+		 */
+		if(t) {
+			*t -= n * nsecperchar;
+			histo[n]++;
+		}
+		p = buf;
+	}
+	n--;
+	return *p++;
+}
+
+void
+getline(char *s, int size, vlong *t){
+	uchar c;
+	char *p;
+	int n, cs;
+
+	for(;;){
+		p = s;
+		n = 0;
+		while((c = getonechar(t)) != '\n' && n < size){
+			t = nil;
+			if(c != '\r'){
+				*p++ = c;
+				n++;
+			}
+		}
+		if(n < size)
+			break;
+		while(getonechar(t) != '\n' && n < 4096)
+			n++;
+		if(n == 4096)
+			sysfatal("preposterous gps line, wrong baud rate?");
+		fprint(2, "ridiculous gps line: %d bytes\n", n);
+	}
+	*p = 0;
+	for(p = s; isdigit(*p); p++)
+		;
+	if(*p++ == '	')
+		memmove(s, p, strlen(p)+1);
+	if(s[0] == '$'){
+		if(n > 4 && s[n-3] == '*'){
+			s[n-3] = 0;
+			p = s+1;
+			cs = 0;
+			while(*p) cs ^= *p++;
+			n = strtol(&s[n-2], nil, 16);
+			if(n != cs){
+				if(debug)
+					fprint(2, "Checksum error %s, 0x%x, 0x%x\n",
+						s, n, cs);
+				checksumerrors++;
+			}
+		}
+	}
+	for(p = s; *p; rawin++)
+		raw[rawin & Rawmask] = *p++;
+	raw[rawin & Rawmask] = '\n';
+	rawin++;
+}

+ 23 - 0
sys/src/cmd/aux/gps/mkfile

@@ -0,0 +1,23 @@
+</$objtype/mkfile
+
+TARG=\
+	gpsfs\
+	gpsevermore\
+
+HFILES=dat.h\
+	
+OFILES=\
+	util.$O
+
+BIN=/$objtype/bin/aux
+
+UPDATE=\
+	mkfile\
+	$HFILES\
+	${OFILES:%.$O=%.c}\
+	${TARG:%=%.c}\
+
+</sys/src/cmd/mkmany
+
+update:V:
+	update $UPDATEFLAGS $UPDATE

+ 174 - 0
sys/src/cmd/aux/gps/util.c

@@ -0,0 +1,174 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+
+Place nowhere = {
+	Undef, Undef
+};
+
+static void
+setlat(Place *p, double lat)
+{
+	p->lat = lat;
+}
+
+static void
+setlon(Place *p, double lon)
+{
+	p->lon = lon;
+}
+
+static int
+printlatlon(char *p, int n, double lat, char po, char ne)
+{
+	char c;
+	double d;
+	int deg, min, sec;
+
+	if(lat > 0)
+		c = po;
+	else if(lat < 0){
+		c = ne;
+		lat = -lat;
+	} else
+		c = ' ';
+	sec = 3600 * modf(lat, &d);
+	deg = d;
+	min = sec/60;
+	sec = sec % 60;
+	return snprint(p, n, "%#3.3d°%#2.2d′%#2.2d″%c", deg, min, sec, c);
+}
+
+int
+placeconv(Fmt *fp)
+{
+	char str[256];
+	int n;
+	Place pl;
+
+	pl = va_arg(fp->args, Place);
+	n = 0;
+	n += printlatlon(str+n, sizeof(str)-n, pl.lat, 'N', 'S');
+	n += snprint(str+n, sizeof(str)-n, ", ");
+	printlatlon(str+n, sizeof(str)-n, pl.lon, 'E', 'W');
+	return fmtstrcpy(fp, str);
+}
+
+int
+strtolatlon(char *p, char **ep, Place *pl)
+{
+	double latlon;
+	int neg = 0;
+
+	while(*p == '0') p++;
+	latlon = strtod(p, &p);
+	if(latlon < 0){
+		latlon = -latlon;
+		neg = 1;
+	}
+	if(*p == ':'){
+		p++;
+		while(*p == '0') p++;
+		latlon += strtod(p, &p)/60.0;
+		if(*p == ':'){
+			p++;
+			while(*p == '0') p++;
+			latlon += strtod(p, &p)/3600.0;
+		}
+	}
+	switch (*p++){
+	case 'N':
+	case 'n':
+		if(neg) latlon = -latlon;
+		if(pl->lat != Undef)
+			return -1;
+		setlat(pl, latlon);
+		break;
+	case 'S':
+	case 's':
+		if(!neg) latlon = -latlon;
+		if(pl->lat != Undef)
+			return -1;
+		setlat(pl, latlon);
+		break;
+	case 'E':
+	case 'e':
+		if(neg) latlon = -latlon;
+		if(pl->lon != Undef)
+			return -1;
+		setlon(pl, latlon);
+		break;
+	case 'W':
+	case 'w':
+		if(!neg) latlon = -latlon;
+		if(pl->lon != Undef)
+			return -1;
+		setlon(pl, latlon);
+		break;
+	case '\0':
+	case ' ':
+	case '\t':
+	case '\n':
+		p--;
+		if(neg) latlon = -latlon;
+		if(pl->lat == Undef){
+			setlat(pl, latlon);
+		} else if(pl->lon == Undef){
+			latlon = -latlon;
+			setlon(pl, latlon);
+		} else return -1;
+		break;
+	default:
+		return -1;
+	}
+	if(ep)
+		*ep = p;
+	return 0;
+}
+
+Place
+strtopos(char *p, char **ep)
+{
+	Place pl = nowhere;
+
+	if(strtolatlon(p, &p, &pl) < 0)
+		return nowhere;
+	while(*p == ' ' || *p == '\t' || *p == '\n')
+		p++;
+	if(strtolatlon(p, &p, &pl) < 0)
+		return nowhere;
+	if(ep)
+		*ep = p;
+	return pl;
+}
+
+static void
+rtcset(long t)		/* We may use this some day */
+{
+	static int fd;
+	long r;
+	int n;
+	char buf[32];
+
+	if(fd <= 0 && (fd = open("#r/rtc", ORDWR)) < 0){
+		fprint(2, "Can't open #r/rtc: %r\n");
+		return;
+	}
+	n = read(fd, buf, sizeof buf - 1);
+	if(n <= 0){
+		fprint(2, "Can't read #r/rtc: %r\n");
+		return;
+	}
+	buf[n] = '\0';
+	r = strtol(buf, nil, 0);
+	if(r <= 0){
+		fprint(2, "ridiculous #r/rtc: %ld\n", r);
+		return;
+	}
+	if(r - t > 1 || t - r > 0){
+		seek(fd, 0, 0);
+		fprint(fd, "%ld", t);
+		fprint(2, "correcting #r/rtc: %ld → %ld\n", r, t);
+	}
+	seek(fd, 0, 0);
+}

+ 1 - 0
sys/src/cmd/aux/mkfile

@@ -45,6 +45,7 @@ UPDATE=\
 
 DIRS=mnihongo\
 	flashfs\
+	gps\
 	na\
 	vga
 

+ 64 - 4
sys/src/cmd/aux/timesync.c

@@ -15,6 +15,7 @@ enum {
 	Rtc,
 	Ntp,
 	Utc,
+	Gps,
 
 	HZAvgSecs=	3*60,	/* target averaging period for the frequency in seconds */
 	MinSampleSecs=	60,	/* minimum sampling time in seconds */
@@ -26,6 +27,7 @@ char *logfile = "timesync";
 char *timeserver;
 char *Rootid;
 int utcfil;
+int gpsfil;
 int debug;
 int impotent;
 int logging;
@@ -104,6 +106,7 @@ static int	caperror(vlong dhz, int tsecs, vlong taccuracy);
 static long	fstime(void);
 static int	gettime(vlong *nsec, uvlong *ticks, uvlong *hz); // returns time, ticks, hz
 static int	getclockprecision(vlong);
+static vlong	gpssample(void);
 static void	hnputts(void *p, vlong nsec);
 static void	hnputts(void *p, vlong nsec);
 static void	inittime(void);
@@ -169,9 +172,10 @@ main(int argc, char **argv)
 	case 'U':
 		type = Utc;
 		stratum = 1;
-		timeserver = ARGF();
-		if (timeserver == nil)
-			sysfatal("bad time source");
+		break;
+	case 'G':
+		type = Gps;
+		stratum = 1;
 		break;
 	case 'n':
 		type = Ntp;
@@ -246,6 +250,18 @@ main(int argc, char **argv)
 		rfork(RFNAMEG);
 
 	switch(type){
+	case Utc:
+		if(argc > 0)
+			timeserver = argv[0];
+		else
+			sysfatal("bad time source");
+		break;
+	case Gps:
+		if(argc > 0)
+			timeserver = argv[0];
+		else
+			timeserver = "/mnt/gps/time";
+		break;
 	case Fs:
 		if(argc > 0)
 			timeserver = argv[0];
@@ -297,6 +313,12 @@ main(int argc, char **argv)
 			sysfatal("opening %s: %r\n", timeserver);
 		utcfil = fd;
 		break;
+	case Gps:
+		fd = open(timeserver, OREAD);
+		if(fd < 0)
+			sysfatal("opening %s: %r\n", timeserver);
+		gpsfil = fd;
+		break;
 	}
 
 	//
@@ -362,11 +384,21 @@ main(int argc, char **argv)
 				continue;
 			}
 			break;
+		case Gps:
+			diff = gpssample();
+			if(diff == 0LL){
+				if(logging)
+					syslog(0, logfile, "no sample");
+				free(s);
+				if(secs > 60*15)
+					tsecs = 60*15;
+				continue;
+			}
 		}
 
 		// use fastest method to read local clock and ticks
 		gettime(&s->ltime, &s->ticks, 0);
-		if(type == Ntp)
+		if(type == Ntp || type == Gps)
 			s->stime = s->ltime + diff;
 
 		// if the sample was bad, ignore it
@@ -975,6 +1007,34 @@ ntptimediff(NTPserver *ns)
 	return -1;
 }
 
+static vlong
+gpssample(void)
+{
+	vlong	l, g, d;
+	int	i, n;
+	char	*v[4], buf[128];
+
+	d = -1000000000000000000LL;
+	for(i = 0; i < 5; i++){
+		sleep(1100);
+		seek(gpsfil, 0, 0);
+		n = read(gpsfil, buf, sizeof buf - 1);
+		if (n <= 0)
+			return(0LL);
+		buf[n] = 0;
+		n = tokenize(buf, v, nelem(v));
+		if(n != 4)
+			return(0LL);
+		if(strcmp(v[3], "A") != 0)
+			return(0LL);
+		g = atoll(v[1]);
+		l = atoll(v[2]);
+		if(g-l > d)
+			d = g-l;
+	}
+	return(d);
+}
+
 static vlong
 ntpsample(void)
 {

+ 114 - 0
sys/src/cmd/unlnfs.c

@@ -0,0 +1,114 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <libsec.h>
+
+enum
+{
+	ENCLEN = 26,
+};
+
+typedef struct Name Name;
+struct Name {
+	char	shortname[ENCLEN + 1];
+	char*	longname;
+	Name*	next;
+};
+
+Name *names;
+void rename(char*, char*, char*);
+void renamedir(char*);
+void readnames(char*);
+
+void
+main(int argc, char **argv)
+{
+	char lnfile[256], *d;
+	d = ".";
+	if(argc > 1)
+		d = argv[1];
+
+	snprint(lnfile, sizeof(lnfile), "%s/.longnames", d);
+	readnames(lnfile);
+	renamedir(d);
+}
+
+void
+renamedir(char *d)
+{
+	int n;
+	Dir *dir;
+	char *sub;
+	int fd, i;
+	uchar digest[MD5dlen];
+	Name *na;
+
+	fd = open(d, OREAD);
+	if (fd == -1)
+		return;
+	while((n = dirread(fd, &dir)) > 0){
+		for(i = 0; i < n; i++){
+			if(dir[i].mode & DMDIR){
+				sub = malloc(strlen(d) + 1 + strlen(dir[i].name) + 1);
+				sprint(sub, "%s/%s", d, dir[i].name);
+				renamedir(sub);
+				free(sub);
+			}
+			if(strlen(dir[i].name) != ENCLEN)
+				continue;
+			for (na = names; na != nil; na = na->next){
+				if (strcmp(na->shortname, dir[i].name) == 0){
+					rename(d, dir[i].name, na->longname);
+					break;
+				}
+			}
+		}
+		free(dir);
+	}
+	close(fd);
+}
+
+void
+rename(char *d, char *old, char *new)
+{
+	char *p;
+	Dir dir;
+	p = malloc(strlen(d) + 1 + strlen(old) + 1);
+	sprint(p, "%s/%s", d, old);
+	nulldir(&dir);
+	dir.name = new;
+	if(dirwstat(p, &dir) == -1)
+		fprint(2, "unlnfs: cannot rename %s to %s: %r\n", p, new);
+	free(p);
+}
+	
+void
+long2short(char shortname[ENCLEN+1], char *longname)
+{
+	uchar digest[MD5dlen];
+	md5((uchar*)longname, strlen(longname), digest, nil);
+	enc32(shortname, ENCLEN+1, digest, MD5dlen);
+}
+
+void
+readnames(char *lnfile)
+{
+	Biobuf *bio;
+	char *f;
+	int slot;
+	Name *n;
+
+	bio = Bopen(lnfile, OREAD);
+	if(bio == nil){
+		fprint(2, "unlnfs: cannot open %s: %r\n", lnfile);
+		exits("error");
+	}
+	while((f = Brdstr(bio, '\n', 1)) != nil){
+		n = malloc(sizeof(Name));
+		n->longname = f;
+		long2short(n->shortname, f);
+		n->next = names;
+		names = n;
+	}
+	Bterm(bio);
+}

+ 10 - 4
sys/src/cmd/upas/marshal/marshal.c

@@ -733,7 +733,7 @@ printdate(Biobuf *b)
 
 	return Bprint(b, "Date: %s, %d %s %d %2.2d:%2.2d:%2.2d %s%.4d\n",
 		ascwday[tm->wday], tm->mday, ascmon[tm->mon], 1900+tm->year,
-		tm->hour, tm->min, tm->sec, tz>0?"+":"", tz);
+		tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz);
 }
 
 int
@@ -745,10 +745,13 @@ printfrom(Biobuf *b)
 int
 printto(Biobuf *b, Addr *a)
 {
+	int i;
+
 	if(Bprint(b, "To: %s", a->v) < 0)
 		return -1;
+	i = 0;
 	for(a = a->next; a != nil; a = a->next)
-		if(Bprint(b, ", %s", a->v) < 0)
+		if(Bprint(b, "%s%s", ((i++ & 7) == 7)?",\n\t":", ", a->v) < 0)
 			return -1;
 	if(Bprint(b, "\n") < 0)
 		return -1;
@@ -758,12 +761,15 @@ printto(Biobuf *b, Addr *a)
 int
 printcc(Biobuf *b, Addr *a)
 {
+	int i;
+
 	if(a == nil)
 		return 0;
 	if(Bprint(b, "CC: %s", a->v) < 0)
 		return -1;
+	i = 0;
 	for(a = a->next; a != nil; a = a->next)
-		if(Bprint(b, ", %s", a->v) < 0)
+		if(Bprint(b, "%s%s", ((i++ & 7) == 7)?",\n\t":", ", a->v) < 0)
 			return -1;
 	if(Bprint(b, "\n") < 0)
 		return -1;
@@ -935,7 +941,7 @@ printunixfrom(int fd)
 	return fprint(fd, "From %s %s %s %d %2.2d:%2.2d:%2.2d %s%.4d %d\n",
 		user,
 		ascwday[tm->wday], ascmon[tm->mon], tm->mday,
-		tm->hour, tm->min, tm->sec, tz>0?"+":"", tz, 1900+tm->year);
+		tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz, 1900+tm->year);
 }
 
 char *specialfile[] =

+ 0 - 35
sys/src/games/music/playlistfs/fs.c

@@ -417,41 +417,6 @@ rread(Worker *w)
 	return nil;
 }
 
-static char*
-qtoken(char *s, char *sep)
-{
-	int quoting;
-	char *t;
-
-	quoting = 0;
-	t = s;	/* s is output string, t is input string */
-	while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){
-		if(*t != '\''){
-			*s++ = *t++;
-			continue;
-		}
-		/* *t is a quote */
-		if(!quoting){
-			quoting = 1;
-			t++;
-			continue;
-		}
-		/* quoting and we're on a quote */
-		if(t[1] != '\''){
-			/* end of quoted section; absorb closing quote */
-			t++;
-			quoting = 0;
-			continue;
-		}
-		/* doubled quote; fold one quote into two */
-		t++;
-		*s++ = *t++;
-	}
-	if(*t == '\0')
-		return nil;
-	return t;
-}
-
 char*
 rwrite(Worker *w)
 {

+ 0 - 3
sys/src/games/music/playlistfs/playlist.h

@@ -80,10 +80,8 @@ struct Playlist {
 };
 
 struct File {
-	QLock;
 	Dir	dir;
 	Channel	*workers;
-	void	*data;
 };
 
 struct Worker
@@ -94,7 +92,6 @@ struct Worker
 
 struct Fid
 {
-	QLock;
 	int	fid;
 	File	*file;
 	ushort	flags;