History

hmmm

echoline committed 10 years ago

Commit 3ffbdfe1 parent 38204fb875 files · +13360 −127336Browse files

Unified · Split

875 files
  1. acme/acid/Acid +6 −0
  2. acme/acid/guide +3 −0
  3. acme/bin/386/Mail +0 −0
  4. acme/bin/386/News +0 −0
  5. acme/bin/386/Wiki +0 −0
  6. acme/bin/386/mkwnew +0 −0
  7. acme/bin/386/spout +0 −0
  8. acme/bin/386/win +0 −0
  9. acme/bin/Battery +30 −0
  10. acme/bin/Isspam +13 −0
  11. acme/bin/Mail +9 −0
  12. acme/bin/Perl +7 −0
  13. acme/bin/README +3 −0
  14. acme/bin/Spam +13 −0
  15. acme/bin/Unspam +13 −0
  16. acme/bin/adiff +24 −0
  17. acme/bin/agrep +3 −0
  18. acme/bin/amd64/Mail +0 −0
  19. acme/bin/amd64/News +0 −0
  20. acme/bin/amd64/Wiki +0 −0
  21. acme/bin/amd64/mkwnew +0 −0
  22. acme/bin/amd64/spout +0 −0
  23. acme/bin/amd64/win +0 −0
  24. acme/bin/ap +12 −0
  25. acme/bin/aspell +43 −0
  26. acme/bin/guide +4 −0
  27. acme/bin/ind +3 −0
  28. acme/bin/new +10 −0
  29. acme/bin/quote +3 −0
  30. acme/bin/source/6.mkwnew +0 −0
  31. acme/bin/source/6.spout +0 −0
  32. acme/bin/source/8.mkwnew +0 −0
  33. acme/bin/source/8.spout +0 −0
  34. acme/bin/source/acd/README +33 −0
  35. acme/bin/source/acd/access +243 −0
  36. acme/bin/source/acd/acd.h +171 −0
  37. acme/bin/source/acd/acme.c +347 −0
  38. acme/bin/source/acd/cddb +206 −0
  39. acme/bin/source/acd/cddb.c +197 −0
  40. acme/bin/source/acd/cddbproto +894 −0
  41. acme/bin/source/acd/discid +159 −0
  42. acme/bin/source/acd/mailinglist +220 −0
  43. acme/bin/source/acd/main.c +135 −0
  44. acme/bin/source/acd/mkfile +22 −0
  45. acme/bin/source/acd/mmc.c +303 −0
  46. acme/bin/source/acd/outline +32 −0
  47. acme/bin/source/acd/submit +220 −0
  48. acme/bin/source/acd/toc.c +59 −0
  49. acme/bin/source/acd/util.c +89 −0
  50. acme/bin/source/acd/win.c +320 −0
  51. acme/bin/source/adict/_adict.c +584 −0
  52. acme/bin/source/adict/_win.c +315 −0
  53. acme/bin/source/adict/adict.c +591 −0
  54. acme/bin/source/adict/adict.h +10 −0
  55. acme/bin/source/adict/man +26 −0
  56. acme/bin/source/adict/mkfile +11 −0
  57. acme/bin/source/adict/win.c +315 −0
  58. acme/bin/source/adict/win.h +59 −0
  59. acme/bin/source/mkfile +27 −0
  60. acme/bin/source/mkwnew.6 +0 −0
  61. acme/bin/source/mkwnew.8 +0 −0
  62. acme/bin/source/mkwnew.c +45 −0
  63. acme/bin/source/spout.6 +0 −0
  64. acme/bin/source/spout.8 +0 −0
  65. acme/bin/source/spout.c +123 −0
  66. acme/bin/source/win/6.out +0 −0
  67. acme/bin/source/win/8.out +0 −0
  68. acme/bin/source/win/dat.h +98 −0
  69. acme/bin/source/win/fs.6 +0 −0
  70. acme/bin/source/win/fs.8 +0 −0
  71. acme/bin/source/win/fs.c +190 −0
  72. acme/bin/source/win/main.6 +0 −0
  73. acme/bin/source/win/main.8 +0 −0
  74. acme/bin/source/win/main.c +643 −0
  75. acme/bin/source/win/mkfile +25 −0
  76. acme/bin/source/win/pipe.6 +0 −0
  77. acme/bin/source/win/pipe.8 +0 −0
  78. acme/bin/source/win/pipe.c +175 −0
  79. acme/bin/source/win/util.6 +0 −0
  80. acme/bin/source/win/util.8 +0 −0
  81. acme/bin/source/win/util.c +90 −0
  82. acme/bin/source/win/win.6 +0 −0
  83. acme/bin/source/win/win.8 +0 −0
  84. acme/bin/source/win/win.c +273 −0
  85. acme/bin/unind +3 −0
  86. acme/bin/wnew +5 −0
  87. acme/mail/guide +4 −0
  88. acme/mail/mkbox +11 −0
  89. acme/mail/readme +57 −0
  90. acme/mail/src/6.out +0 −0
  91. acme/mail/src/8.out +0 −0
  92. acme/mail/src/dat.h +164 −0
  93. acme/mail/src/html.6 +0 −0
  94. acme/mail/src/html.8 +0 −0
  95. acme/mail/src/html.c +75 −0
  96. acme/mail/src/mail.6 +0 −0
  97. acme/mail/src/mail.8 +0 −0
  98. acme/mail/src/mail.c +550 −0
  99. acme/mail/src/mesg.6 +0 −0
  100. acme/mail/src/mesg.8 +0 −0
  101. acme/mail/src/mesg.c +1322 −0
  102. acme/mail/src/mkfile +30 −0
  103. acme/mail/src/reply.6 +0 −0
  104. acme/mail/src/reply.8 +0 −0
  105. acme/mail/src/reply.c +567 −0
  106. acme/mail/src/util.6 +0 −0
  107. acme/mail/src/util.8 +0 −0
  108. acme/mail/src/util.c +105 −0
  109. acme/mail/src/win.6 +0 −0
  110. acme/mail/src/win.8 +0 −0
  111. acme/mail/src/win.c +341 −0
  112. acme/mkfile +10 −0
  113. acme/news/guide +2 −0
  114. acme/news/src/6.out +0 −0
  115. acme/news/src/8.out +0 −0
  116. acme/news/src/mkfile +18 −0
  117. acme/news/src/news.6 +0 −0
  118. acme/news/src/news.8 +0 −0
  119. acme/news/src/news.c +1007 −0
  120. acme/news/src/util.6 +0 −0
  121. acme/news/src/util.8 +0 −0
  122. acme/news/src/util.c +106 −0
  123. acme/news/src/win.6 +0 −0
  124. acme/news/src/win.8 +0 −0
  125. acme/news/src/win.c +324 −0
  126. acme/news/src/win.h +75 −0
  127. acme/wiki/guide +3 −0
  128. acme/wiki/src/6.out +0 −0
  129. acme/wiki/src/8.out +0 −0
  130. acme/wiki/src/awiki.h +114 −0
  131. acme/wiki/src/main.6 +0 −0
  132. acme/wiki/src/main.8 +0 −0
  133. acme/wiki/src/main.c +60 −0
  134. acme/wiki/src/mkfile +14 −0
  135. acme/wiki/src/util.6 +0 −0
  136. acme/wiki/src/util.8 +0 −0
  137. acme/wiki/src/util.c +89 −0
  138. acme/wiki/src/wiki.6 +0 −0
  139. acme/wiki/src/wiki.8 +0 −0
  140. acme/wiki/src/wiki.c +602 −0
  141. acme/wiki/src/win.6 +0 −0
  142. acme/wiki/src/win.8 +0 −0
  143. acme/wiki/src/win.c +341 −0
  144. acme/wiki/wiki.diff +27 −0
  145. sys/games/lib/4scores +0 −0
  146. sys/games/lib/5scores +0 −0
  147. sys/games/lib/anawords +0 −18766
  148. sys/games/lib/fortunes +0 −5235
  149. sys/games/lib/fortunes.index +0 −0
  150. sys/games/lib/life/2.eaters +0 −9
  151. sys/games/lib/life/34osc +0 −47
  152. sys/games/lib/life/55555 +0 −1
  153. sys/games/lib/life/5row +0 −1
  154. sys/games/lib/life/acorn +0 −3
  155. sys/games/lib/life/background1 +0 −59
  156. sys/games/lib/life/baker +0 −95
  157. sys/games/lib/life/bakery +0 −5
  158. sys/games/lib/life/barber.pole +0 −19
  159. sys/games/lib/life/barberpole +0 −13
  160. sys/games/lib/life/beacon +0 −4
  161. sys/games/lib/life/beaconmaker +0 −25
  162. sys/games/lib/life/benchmark +0 −4
  163. sys/games/lib/life/bheptomino +0 −3
  164. sys/games/lib/life/biclock +0 −7
  165. sys/games/lib/life/billiard.clock +0 −12
  166. sys/games/lib/life/billiard1 +0 −8
  167. sys/games/lib/life/billiard2 +0 −10
  168. sys/games/lib/life/billiard3 +0 −12
  169. sys/games/lib/life/billiard4 +0 −13
  170. sys/games/lib/life/billiard5 +0 −15
  171. sys/games/lib/life/billiard6 +0 −14
  172. sys/games/lib/life/billiardgeorge +0 −19
  173. sys/games/lib/life/billiardsmall +0 −5
  174. sys/games/lib/life/biloaf +0 −4
  175. sys/games/lib/life/blanker +0 −2
  176. sys/games/lib/life/blinker +0 −1
  177. sys/games/lib/life/blinkership +0 −17
  178. sys/games/lib/life/block +0 −2
  179. sys/games/lib/life/boat.factory +0 −98
  180. sys/games/lib/life/boatcap +0 −14
  181. sys/games/lib/life/boatmaker +0 −26
  182. sys/games/lib/life/breeder +0 −338
  183. sys/games/lib/life/breeder4753 +0 −337
  184. sys/games/lib/life/c1 +0 −5
  185. sys/games/lib/life/c2 +0 −11
  186. sys/games/lib/life/c3 +0 −17
  187. sys/games/lib/life/c4 +0 −23
  188. sys/games/lib/life/c5 +0 −29
  189. sys/games/lib/life/c6 +0 −35
  190. sys/games/lib/life/c7 +0 −41
  191. sys/games/lib/life/c8 +0 −47
  192. sys/games/lib/life/c9 +0 −53
  193. sys/games/lib/life/candelabra +0 −6
  194. sys/games/lib/life/capsule8 +0 −11
  195. sys/games/lib/life/catherinewheel +0 −12
  196. sys/games/lib/life/cheshire.cat +0 −6
  197. sys/games/lib/life/cheshirecat +0 −6
  198. sys/games/lib/life/clappinghands +0 −4
  199. sys/games/lib/life/clean.fuse +0 −159
  200. sys/games/lib/life/clock +0 −4
  201. sys/games/lib/life/clock2 +0 −12
  202. sys/games/lib/life/cmu +0 −15
  203. sys/games/lib/life/cmu2 +0 −17
  204. sys/games/lib/life/cmu3 +0 −19
  205. sys/games/lib/life/collapsecap +0 −14
  206. sys/games/lib/life/cow +0 −7
  207. sys/games/lib/life/cp.48-56-72 +0 −13
  208. sys/games/lib/life/crab +0 −7
  209. sys/games/lib/life/cross +0 −4
  210. sys/games/lib/life/diagfuse +0 −16
  211. sys/games/lib/life/diamond +0 −8
  212. sys/games/lib/life/dirty.fuse +0 −159
  213. sys/games/lib/life/eaters3 +0 −9
  214. sys/games/lib/life/eden +0 −9
  215. sys/games/lib/life/figure8 +0 −6
  216. sys/games/lib/life/fisheater +0 −18
  217. sys/games/lib/life/flare.path +0 −97
  218. sys/games/lib/life/flasher +0 −3
  219. sys/games/lib/life/flip.flop +0 −8
  220. sys/games/lib/life/flotilla +0 −52
  221. sys/games/lib/life/flywheel +0 −4
  222. sys/games/lib/life/fool +0 −12
  223. sys/games/lib/life/fusebranch +0 −26
  224. sys/games/lib/life/fusecorner +0 −18
  225. sys/games/lib/life/fusehinge +0 −14
  226. sys/games/lib/life/futility +0 −34
  227. sys/games/lib/life/fuzzcapsule +0 −12
  228. sys/games/lib/life/gear +0 −8
  229. sys/games/lib/life/glider +0 −3
  230. sys/games/lib/life/glider.f +0 −5
  231. sys/games/lib/life/glider.gun +0 −9
  232. sys/games/lib/life/glider.havoc +0 −5
  233. sys/games/lib/life/glider.step +0 −9
  234. sys/games/lib/life/glider.thing1 +0 −3
  235. sys/games/lib/life/glider.thing2 +0 −7
  236. sys/games/lib/life/gliderarmyof25 +0 −78
  237. sys/games/lib/life/glidercap1 +0 −14
  238. sys/games/lib/life/glidercap2 +0 −14
  239. sys/games/lib/life/glidercap3 +0 −20
  240. sys/games/lib/life/glidercap4 +0 −18
  241. sys/games/lib/life/glidercap5 +0 −17
  242. sys/games/lib/life/gliderglidergu +0 −25
  243. sys/games/lib/life/glidergun +0 −12
  244. sys/games/lib/life/glidergun2 +0 −34
  245. sys/games/lib/life/gliders.12 +0 −5
  246. sys/games/lib/life/gliders.hex +0 −9
  247. sys/games/lib/life/gosper.flop +0 −72
  248. sys/games/lib/life/greymatter1 +0 −26
  249. sys/games/lib/life/gun.builder +0 −6
  250. sys/games/lib/life/gun.gliders +0 −21
  251. sys/games/lib/life/gunandeater +0 −21
  252. sys/games/lib/life/h.heptomino +0 −3
  253. sys/games/lib/life/harvester +0 −96
  254. sys/games/lib/life/heavy.ship +0 −4
  255. sys/games/lib/life/hepto.shuttle +0 −11
  256. sys/games/lib/life/hertz.osc +0 −17
  257. sys/games/lib/life/horizfuse +0 −2
  258. sys/games/lib/life/j +0 −3
  259. sys/games/lib/life/kickback +0 −7
  260. sys/games/lib/life/lambdabomb +0 −2
  261. sys/games/lib/life/largefish +0 −4
  262. sys/games/lib/life/light.ship +0 −4
  263. sys/games/lib/life/longfuse +0 −6
  264. sys/games/lib/life/longfuse2 +0 −6
  265. sys/games/lib/life/mathematician +0 −12
  266. sys/games/lib/life/mediumfish +0 −4
  267. sys/games/lib/life/mediumfishgun +0 −91
  268. sys/games/lib/life/methuselah +0 −3
  269. sys/games/lib/life/middle.ship +0 −4
  270. sys/games/lib/life/mip +0 −4
  271. sys/games/lib/life/morejunk +0 −7
  272. sys/games/lib/life/new.gun +0 −34
  273. sys/games/lib/life/osc26 +0 −39
  274. sys/games/lib/life/osc28 +0 −14
  275. sys/games/lib/life/osc55 +0 −27
  276. sys/games/lib/life/osc66 +0 −32
  277. sys/games/lib/life/osc72 +0 −8
  278. sys/games/lib/life/oscillator1 +0 −5
  279. sys/games/lib/life/oscillator2 +0 −7
  280. sys/games/lib/life/oscillator3 +0 −7
  281. sys/games/lib/life/overw8.ship +0 −16
  282. sys/games/lib/life/penta.bounce +0 −4
  283. sys/games/lib/life/penta.death +0 −7
  284. sys/games/lib/life/penta.kill +0 −8
  285. sys/games/lib/life/penta.shuttle +0 −8
  286. sys/games/lib/life/pentadecathlon +0 −1
  287. sys/games/lib/life/pi.heptomino +0 −3
  288. sys/games/lib/life/piecollection +0 −10
  289. sys/games/lib/life/pifuse +0 −56
  290. sys/games/lib/life/piston +0 −7
  291. sys/games/lib/life/piston2 +0 −11
  292. sys/games/lib/life/pjw +0 −48
  293. sys/games/lib/life/puffer.train +0 −18
  294. sys/games/lib/life/pulsar-48-56-7 +0 −3
  295. sys/games/lib/life/pulse1 +0 −7
  296. sys/games/lib/life/pulse2 +0 −8
  297. sys/games/lib/life/pump +0 −6
  298. sys/games/lib/life/queen.bee +0 −7
  299. sys/games/lib/life/r +0 −4
  300. sys/games/lib/life/r.pentomino +0 −3
  301. sys/games/lib/life/rake +0 −19
  302. sys/games/lib/life/rake2 +0 −33
  303. sys/games/lib/life/relay +0 −7
  304. sys/games/lib/life/round +0 −70
  305. sys/games/lib/life/rpentomino +0 −3
  306. sys/games/lib/life/s.glider +0 −8
  307. sys/games/lib/life/saint +0 −63
  308. sys/games/lib/life/shiningflower +0 −6
  309. sys/games/lib/life/ships.appear +0 −6
  310. sys/games/lib/life/ships.gliders +0 −4
  311. sys/games/lib/life/ships.vanish +0 −6
  312. sys/games/lib/life/shuttle +0 −7
  313. sys/games/lib/life/sixgliders +0 −8
  314. sys/games/lib/life/skyline +0 −5
  315. sys/games/lib/life/smallfish +0 −4
  316. sys/games/lib/life/somejunk +0 −7
  317. sys/games/lib/life/spark +0 −5
  318. sys/games/lib/life/spark2 +0 −5
  319. sys/games/lib/life/sparkfuse +0 −5
  320. sys/games/lib/life/sparktopifuse +0 −25
  321. sys/games/lib/life/sq.11 +0 −13
  322. sys/games/lib/life/sq.9 +0 −11
  323. sys/games/lib/life/squareblinker +0 −4
  324. sys/games/lib/life/squarecap +0 −14
  325. sys/games/lib/life/squaredance +0 −7
  326. sys/games/lib/life/stargaterepeat +0 −13
  327. sys/games/lib/life/still +0 −30
  328. sys/games/lib/life/still.lives +0 −27
  329. sys/games/lib/life/swastika +0 −5
  330. sys/games/lib/life/switch.block +0 −6
  331. sys/games/lib/life/switch.engine +0 −6
  332. sys/games/lib/life/testtube +0 −19
  333. sys/games/lib/life/thunderbird +0 −5
  334. sys/games/lib/life/thunderbirdfus +0 −21
  335. sys/games/lib/life/time.bomb +0 −6
  336. sys/games/lib/life/toad +0 −2
  337. sys/games/lib/life/tumblers +0 −6
  338. sys/games/lib/life/turbine8 +0 −9
  339. sys/games/lib/life/virus.dies +0 −29
  340. sys/games/lib/life/virus.lives +0 −29
  341. sys/games/lib/life/washerwoman +0 −5
  342. sys/games/lib/life/wave1 +0 −15
  343. sys/games/lib/life/weird.wheel +0 −30
  344. sys/games/lib/mahjongg/backgrounds/default.bit +0 −0
  345. sys/games/lib/mahjongg/images/border.bit +0 −0
  346. sys/games/lib/mahjongg/images/gameover.bit +0 −0
  347. sys/games/lib/mahjongg/images/mask.bit +0 −0
  348. sys/games/lib/mahjongg/layouts/default.layout +0 −81
  349. sys/games/lib/mahjongg/tilesets/default.tileset +0 −0
  350. sys/games/lib/sokoban/images/cargo.bit +0 −0
  351. sys/games/lib/sokoban/images/empty.bit +0 −0
  352. sys/games/lib/sokoban/images/goal.bit +0 −0
  353. sys/games/lib/sokoban/images/goalcargo.bit +0 −0
  354. sys/games/lib/sokoban/images/left.bit +0 −0
  355. sys/games/lib/sokoban/images/right.bit +0 −0
  356. sys/games/lib/sokoban/images/wall.bit +0 −0
  357. sys/games/lib/sokoban/images/win.bit +0 −0
  358. sys/games/lib/sokoban/levels/easy.slc +0 −1549
  359. sys/games/lib/sokoban/levels/hard.slc +0 −1521
  360. sys/games/lib/sudoku/boards/easy-2005-01-21.su +0 −18
  361. sys/games/lib/sudoku/boards/easy-2005-01-23.su +0 −18
  362. sys/games/lib/sudoku/boards/easy-2005-01-25.su +0 −18
  363. sys/games/lib/sudoku/boards/easy-2005-01-29.su +0 −18
  364. sys/games/lib/sudoku/boards/easy-2005-01-30.su +0 −18
  365. sys/games/lib/sudoku/boards/easy-2005-02-02.su +0 −18
  366. sys/games/lib/sudoku/boards/easy-2005-02-03.su +0 −18
  367. sys/games/lib/sudoku/boards/easy-2005-02-04.su +0 −18
  368. sys/games/lib/sudoku/boards/easy-2005-02-06.su +0 −18
  369. sys/games/lib/sudoku/boards/easy-2005-02-07.su +0 −18
  370. sys/games/lib/sudoku/boards/easy-2005-02-08.su +0 −18
  371. sys/games/lib/sudoku/boards/easy-2005-02-09.su +0 −18
  372. sys/games/lib/sudoku/boards/easy-2005-02-10.su +0 −18
  373. sys/games/lib/sudoku/boards/easy-2005-02-11.su +0 −18
  374. sys/games/lib/sudoku/boards/easy-2005-02-12.su +0 −18
  375. sys/games/lib/sudoku/boards/easy-2005-02-13.su +0 −18
  376. sys/games/lib/sudoku/boards/easy-2005-02-14.su +0 −18
  377. sys/games/lib/sudoku/boards/easy-2005-02-16.su +0 −18
  378. sys/games/lib/sudoku/boards/easy-2005-02-17.su +0 −18
  379. sys/games/lib/sudoku/boards/easy-2005-03-03.su +0 −18
  380. sys/games/lib/sudoku/boards/easy-2005-03-04.su +0 −18
  381. sys/games/lib/sudoku/boards/easy-2005-03-05.su +0 −18
  382. sys/games/lib/sudoku/boards/easy-2005-03-06.su +0 −18
  383. sys/games/lib/sudoku/boards/easy-2005-03-07.su +0 −18
  384. sys/games/lib/sudoku/boards/easy-2005-03-08.su +0 −18
  385. sys/games/lib/sudoku/boards/easy-2005-03-09.su +0 −18
  386. sys/games/lib/sudoku/boards/easy-2005-03-10.su +0 −18
  387. sys/games/lib/sudoku/boards/easy-2005-03-11.su +0 −18
  388. sys/games/lib/sudoku/boards/easy-2005-03-12.su +0 −18
  389. sys/games/lib/sudoku/boards/easy-2005-03-29.su +0 −18
  390. sys/games/lib/sudoku/boards/easy-2005-04-11.su +0 −18
  391. sys/games/lib/sudoku/boards/easy-2005-04-26.su +0 −18
  392. sys/games/lib/sudoku/boards/easy-2005-04-28.su +0 −18
  393. sys/games/lib/sudoku/boards/easy-2005-05-24.su +0 −18
  394. sys/games/lib/sudoku/boards/easy000.su +0 −18
  395. sys/games/lib/sudoku/boards/easy001.su +0 −18
  396. sys/games/lib/sudoku/boards/easy002.su +0 −18
  397. sys/games/lib/sudoku/boards/hard-2005-03-13.su +0 −18
  398. sys/games/lib/sudoku/boards/hard-2005-03-14.su +0 −18
  399. sys/games/lib/sudoku/boards/hard-2005-03-19.su +0 −18
  400. sys/games/lib/sudoku/boards/hard-2005-03-26.su +0 −18
  401. sys/games/lib/sudoku/boards/hard-2005-03-27.su +0 −18
  402. sys/games/lib/sudoku/boards/hard-2005-04-02.su +0 −18
  403. sys/games/lib/sudoku/boards/hard-2005-04-03.su +0 −18
  404. sys/games/lib/sudoku/boards/hard-2005-04-07.su +0 −18
  405. sys/games/lib/sudoku/boards/hard-2005-04-08.su +0 −18
  406. sys/games/lib/sudoku/boards/hard-2005-04-09.su +0 −18
  407. sys/games/lib/sudoku/boards/hard-2005-04-17.su +0 −18
  408. sys/games/lib/sudoku/boards/hard-2005-04-22.su +0 −18
  409. sys/games/lib/sudoku/boards/hard-2005-04-23.su +0 −18
  410. sys/games/lib/sudoku/boards/hard-2005-04-24.su +0 −18
  411. sys/games/lib/sudoku/boards/hard-2005-04-30.su +0 −18
  412. sys/games/lib/sudoku/boards/hard-2005-05-01.su +0 −18
  413. sys/games/lib/sudoku/boards/hard-2005-05-07.su +0 −18
  414. sys/games/lib/sudoku/boards/hard-2005-05-14.su +0 −18
  415. sys/games/lib/sudoku/boards/hard-2005-05-15.su +0 −18
  416. sys/games/lib/sudoku/boards/hard-2005-05-19.su +0 −18
  417. sys/games/lib/sudoku/boards/hard-2005-05-21.su +0 −18
  418. sys/games/lib/sudoku/boards/hard-2005-05-22.su +0 −18
  419. sys/games/lib/sudoku/boards/hard-2005-05-23.su +0 −18
  420. sys/games/lib/sudoku/boards/hard000.su +0 −18
  421. sys/games/lib/sudoku/boards/medium-2005-01-22.su +0 −18
  422. sys/games/lib/sudoku/boards/medium-2005-01-24.su +0 −18
  423. sys/games/lib/sudoku/boards/medium-2005-01-26.su +0 −18
  424. sys/games/lib/sudoku/boards/medium-2005-01-27.su +0 −18
  425. sys/games/lib/sudoku/boards/medium-2005-01-28.su +0 −18
  426. sys/games/lib/sudoku/boards/medium-2005-01-31.su +0 −18
  427. sys/games/lib/sudoku/boards/medium-2005-02-01.su +0 −18
  428. sys/games/lib/sudoku/boards/medium-2005-02-05.su +0 −18
  429. sys/games/lib/sudoku/boards/medium-2005-02-15.su +0 −18
  430. sys/games/lib/sudoku/boards/medium-2005-02-18.su +0 −18
  431. sys/games/lib/sudoku/boards/medium-2005-02-19.su +0 −18
  432. sys/games/lib/sudoku/boards/medium-2005-02-20.su +0 −18
  433. sys/games/lib/sudoku/boards/medium-2005-02-21.su +0 −18
  434. sys/games/lib/sudoku/boards/medium-2005-02-22.su +0 −18
  435. sys/games/lib/sudoku/boards/medium-2005-02-23.su +0 −18
  436. sys/games/lib/sudoku/boards/medium-2005-02-24.su +0 −18
  437. sys/games/lib/sudoku/boards/medium-2005-02-25.su +0 −18
  438. sys/games/lib/sudoku/boards/medium-2005-02-26.su +0 −18
  439. sys/games/lib/sudoku/boards/medium-2005-02-27.su +0 −18
  440. sys/games/lib/sudoku/boards/medium-2005-02-28.su +0 −18
  441. sys/games/lib/sudoku/boards/medium-2005-03-01.su +0 −18
  442. sys/games/lib/sudoku/boards/medium-2005-03-02.su +0 −18
  443. sys/games/lib/sudoku/boards/medium-2005-03-15.su +0 −18
  444. sys/games/lib/sudoku/boards/medium-2005-03-16.su +0 −18
  445. sys/games/lib/sudoku/boards/medium-2005-03-18.su +0 −18
  446. sys/games/lib/sudoku/boards/medium-2005-03-21.su +0 −18
  447. sys/games/lib/sudoku/boards/medium-2005-03-22.su +0 −18
  448. sys/games/lib/sudoku/boards/medium-2005-03-23.su +0 −18
  449. sys/games/lib/sudoku/boards/medium-2005-03-24.su +0 −18
  450. sys/games/lib/sudoku/boards/medium-2005-03-28.su +0 −18
  451. sys/games/lib/sudoku/boards/medium-2005-03-30.su +0 −18
  452. sys/games/lib/sudoku/boards/medium-2005-03-31.su +0 −18
  453. sys/games/lib/sudoku/boards/medium-2005-04-01.su +0 −18
  454. sys/games/lib/sudoku/boards/medium-2005-04-04.su +0 −18
  455. sys/games/lib/sudoku/boards/medium-2005-04-05.su +0 −18
  456. sys/games/lib/sudoku/boards/medium-2005-04-06.su +0 −18
  457. sys/games/lib/sudoku/boards/medium-2005-04-12.su +0 −18
  458. sys/games/lib/sudoku/boards/medium-2005-04-13.su +0 −18
  459. sys/games/lib/sudoku/boards/medium-2005-04-14.su +0 −18
  460. sys/games/lib/sudoku/boards/medium-2005-04-15.su +0 −18
  461. sys/games/lib/sudoku/boards/medium-2005-04-18.su +0 −18
  462. sys/games/lib/sudoku/boards/medium-2005-04-19.su +0 −18
  463. sys/games/lib/sudoku/boards/medium-2005-04-20.su +0 −18
  464. sys/games/lib/sudoku/boards/medium-2005-04-21.su +0 −18
  465. sys/games/lib/sudoku/boards/medium-2005-04-25.su +0 −18
  466. sys/games/lib/sudoku/boards/medium-2005-04-27.su +0 −18
  467. sys/games/lib/sudoku/boards/medium-2005-04-29.su +0 −18
  468. sys/games/lib/sudoku/boards/medium-2005-05-02.su +0 −18
  469. sys/games/lib/sudoku/boards/medium-2005-05-03.su +0 −18
  470. sys/games/lib/sudoku/boards/medium-2005-05-04.su +0 −18
  471. sys/games/lib/sudoku/boards/medium-2005-05-05.su +0 −18
  472. sys/games/lib/sudoku/boards/medium-2005-05-06.su +0 −18
  473. sys/games/lib/sudoku/boards/medium-2005-05-09.su +0 −18
  474. sys/games/lib/sudoku/boards/medium-2005-05-10.su +0 −18
  475. sys/games/lib/sudoku/boards/medium-2005-05-11.su +0 −18
  476. sys/games/lib/sudoku/boards/medium-2005-05-12.su +0 −18
  477. sys/games/lib/sudoku/boards/medium-2005-05-13.su +0 −18
  478. sys/games/lib/sudoku/boards/medium-2005-05-16.su +0 −18
  479. sys/games/lib/sudoku/boards/medium-2005-05-17.su +0 −18
  480. sys/games/lib/sudoku/boards/medium-2005-05-18.su +0 −18
  481. sys/games/lib/sudoku/boards/medium-2005-05-20.su +0 −18
  482. sys/games/lib/sudoku/boards/medium-2005-05-25.su +0 −18
  483. sys/games/lib/sudoku/boards/medium-2005-05-26.su +0 −18
  484. sys/games/lib/sudoku/boards/medium-2005-05-27.su +0 −18
  485. sys/games/lib/sudoku/boards/medium000.su +0 −18
  486. sys/games/lib/sudoku/boards/medium002.su +0 −18
  487. sys/games/lib/sudoku/boards/medium003.su +0 −18
  488. sys/games/lib/sudoku/boards/veasy000.su +0 −18
  489. sys/games/lib/sudoku/boards/veasy001.su +0 −18
  490. sys/games/lib/sudoku/boards/vhard-2005-03-17.su +0 −18
  491. sys/games/lib/sudoku/boards/vhard-2005-03-20.su +0 −18
  492. sys/games/lib/sudoku/boards/vhard-2005-03-25.su +0 −18
  493. sys/games/lib/sudoku/boards/vhard-2005-04-10.su +0 −18
  494. sys/games/lib/sudoku/boards/vhard-2005-04-16.su +0 −18
  495. sys/games/lib/sudoku/boards/vhard-2005-05-08.su +0 −18
  496. sys/games/lib/sudoku/images/1.bit +0 −0
  497. sys/games/lib/sudoku/images/2.bit +0 −0
  498. sys/games/lib/sudoku/images/3.bit +0 −0
  499. sys/games/lib/sudoku/images/4.bit +0 −0
  500. sys/games/lib/sudoku/images/5.bit +0 −0
  501. sys/games/lib/sudoku/images/6.bit +0 −0
  502. sys/games/lib/sudoku/images/7.bit +0 −0
  503. sys/games/lib/sudoku/images/8.bit +0 −0
  504. sys/games/lib/sudoku/images/9.bit +0 −0
  505. sys/src/cmd/gs/386.h +10 −1
  506. sys/src/games/4s.c +0 −43
  507. sys/src/games/5s.c +0 −99
  508. sys/src/games/ana.c +0 −451
  509. sys/src/games/blabs/blabs.c +0 −831
  510. sys/src/games/blabs/mkface +0 −37
  511. sys/src/games/blabs/mkfile +0 −31
  512. sys/src/games/c64/c64.c +0 −382
  513. sys/src/games/c64/cpu.c +0 −514
  514. sys/src/games/c64/dat.h +0 −95
  515. sys/src/games/c64/fns.h +0 −11
  516. sys/src/games/c64/mem.c +0 −307
  517. sys/src/games/c64/mkfile +0 −13
  518. sys/src/games/c64/vic.c +0 −370
  519. sys/src/games/catback.p +0 −481
  520. sys/src/games/catclock.c +0 −387
  521. sys/src/games/doom/am_map.c +0 −1345
  522. sys/src/games/doom/am_map.h +0 −52
  523. sys/src/games/doom/d_englsh.h +0 −701
  524. sys/src/games/doom/d_event.h +0 −123
  525. sys/src/games/doom/d_french.h +0 −433
  526. sys/src/games/doom/d_items.c +0 −138
  527. sys/src/games/doom/d_items.h +0 −52
  528. sys/src/games/doom/d_main.c +0 −1093
  529. sys/src/games/doom/d_main.h +0 −64
  530. sys/src/games/doom/d_net.c +0 −760
  531. sys/src/games/doom/d_net.h +0 −148
  532. sys/src/games/doom/d_player.h +0 −213
  533. sys/src/games/doom/d_textur.h +0 −51
  534. sys/src/games/doom/d_think.h +0 −69
  535. sys/src/games/doom/d_ticcmd.h +0 −55
  536. sys/src/games/doom/doomdata.h +0 −223
  537. sys/src/games/doom/doomdef.c +0 −38
  538. sys/src/games/doom/doomdef.h +0 −322
  539. sys/src/games/doom/doomstat.c +0 −39
  540. sys/src/games/doom/doomstat.h +0 −296
  541. sys/src/games/doom/doomtype.h +0 −66
  542. sys/src/games/doom/dstrings.c +0 −72
  543. sys/src/games/doom/dstrings.h +0 −66
  544. sys/src/games/doom/f_finale.c +0 −738
  545. sys/src/games/doom/f_finale.h +0 −53
  546. sys/src/games/doom/f_wipe.c +0 −301
  547. sys/src/games/doom/f_wipe.h +0 −71
  548. sys/src/games/doom/g_game.c +0 −1676
  549. sys/src/games/doom/g_game.h +0 −79
  550. sys/src/games/doom/hu_lib.c +0 −354
  551. sys/src/games/doom/hu_lib.h +0 −196
  552. sys/src/games/doom/hu_stuff.c +0 −638
  553. sys/src/games/doom/hu_stuff.h +0 −66
  554. sys/src/games/doom/i_main.c +0 −12
  555. sys/src/games/doom/i_net.c +0 −161
  556. sys/src/games/doom/i_net.h +0 −45
  557. sys/src/games/doom/i_sound.c +0 −523
  558. sys/src/games/doom/i_sound.h +0 −115
  559. sys/src/games/doom/i_system.c +0 −144
  560. sys/src/games/doom/i_system.h +0 −106
  561. sys/src/games/doom/i_video.c +0 −372
  562. sys/src/games/doom/i_video.h +0 −63
  563. sys/src/games/doom/info.c +0 −4664
  564. sys/src/games/doom/info.h +0 −1339
  565. sys/src/games/doom/m_argv.c +0 −55
  566. sys/src/games/doom/m_argv.h +0 −42
  567. sys/src/games/doom/m_bbox.c +0 −60
  568. sys/src/games/doom/m_bbox.h +0 −54
  569. sys/src/games/doom/m_cheat.c +0 −101
  570. sys/src/games/doom/m_cheat.h +0 −58
  571. sys/src/games/doom/m_fixed.c +0 −64
  572. sys/src/games/doom/m_fixed.h +0 −50
  573. sys/src/games/doom/m_menu.c +0 −1878
  574. sys/src/games/doom/m_menu.h +0 −67
  575. sys/src/games/doom/m_misc.c +0 −475
  576. sys/src/games/doom/m_misc.h +0 −65
  577. sys/src/games/doom/m_random.c +0 −82
  578. sys/src/games/doom/m_random.h +0 −48
  579. sys/src/games/doom/m_swap.c +0 −57
  580. sys/src/games/doom/m_swap.h +0 −52
  581. sys/src/games/doom/mkfile +0 −142
  582. sys/src/games/doom/p_ceilng.c +0 −335
  583. sys/src/games/doom/p_doors.c +0 −535
  584. sys/src/games/doom/p_enemy.c +0 −2046
  585. sys/src/games/doom/p_floor.c +0 −547
  586. sys/src/games/doom/p_inter.c +0 −918
  587. sys/src/games/doom/p_inter.h +0 −41
  588. sys/src/games/doom/p_lights.c +0 −361
  589. sys/src/games/doom/p_local.h +0 −291
  590. sys/src/games/doom/p_map.c +0 −1337
  591. sys/src/games/doom/p_maputl.c +0 −836
  592. sys/src/games/doom/p_mobj.c +0 −990
  593. sys/src/games/doom/p_mobj.h +0 −295
  594. sys/src/games/doom/p_plats.c +0 −314
  595. sys/src/games/doom/p_pspr.c +0 −864
  596. sys/src/games/doom/p_pspr.h +0 −82
  597. sys/src/games/doom/p_saveg.c +0 −584
  598. sys/src/games/doom/p_saveg.h +0 −51
  599. sys/src/games/doom/p_setup.c +0 −689
  600. sys/src/games/doom/p_setup.h +0 −46
  601. sys/src/games/doom/p_sight.c +0 −349
  602. sys/src/games/doom/p_spec.c +0 −1354
  603. sys/src/games/doom/p_spec.h +0 −559
  604. sys/src/games/doom/p_switch.c +0 −642
  605. sys/src/games/doom/p_telept.c +0 −132
  606. sys/src/games/doom/p_tick.c +0 −147
  607. sys/src/games/doom/p_tick.h +0 −44
  608. sys/src/games/doom/p_user.c +0 −386
  609. sys/src/games/doom/r_bsp.c +0 −580
  610. sys/src/games/doom/r_bsp.h +0 −72
  611. sys/src/games/doom/r_data.c +0 −853
  612. sys/src/games/doom/r_data.h +0 −62
  613. sys/src/games/doom/r_defs.h +0 −490
  614. sys/src/games/doom/r_draw.c +0 −743
  615. sys/src/games/doom/r_draw.h +0 −115
  616. sys/src/games/doom/r_local.h +0 −53
  617. sys/src/games/doom/r_main.c +0 −806
  618. sys/src/games/doom/r_main.h +0 −172
  619. sys/src/games/doom/r_plane.c +0 −451
  620. sys/src/games/doom/r_plane.h +0 −87
  621. sys/src/games/doom/r_segs.c +0 −726
  622. sys/src/games/doom/r_segs.h +0 −44
  623. sys/src/games/doom/r_sky.c +0 −62
  624. sys/src/games/doom/r_sky.h +0 −48
  625. sys/src/games/doom/r_state.h +0 −138
  626. sys/src/games/doom/r_things.c +0 −991
  627. sys/src/games/doom/r_things.h +0 −72
  628. sys/src/games/doom/s_sound.c +0 −804
  629. sys/src/games/doom/s_sound.h +0 −109
  630. sys/src/games/doom/sounds.c +0 −228
  631. sys/src/games/doom/sounds.h +0 −289
  632. sys/src/games/doom/st_lib.c +0 −293
  633. sys/src/games/doom/st_lib.h +0 −226
  634. sys/src/games/doom/st_stuff.c +0 −1468
  635. sys/src/games/doom/st_stuff.h +0 −86
  636. sys/src/games/doom/tables.c +0 −2130
  637. sys/src/games/doom/tables.h +0 −92
  638. sys/src/games/doom/v_video.c +0 −493
  639. sys/src/games/doom/v_video.h +0 −119
  640. sys/src/games/doom/w_wad.c +0 −576
  641. sys/src/games/doom/w_wad.h +0 −78
  642. sys/src/games/doom/wi_stuff.c +0 −1844
  643. sys/src/games/doom/wi_stuff.h +0 −54
  644. sys/src/games/doom/z_zone.c +0 −466
  645. sys/src/games/doom/z_zone.h +0 −86
  646. sys/src/games/eyes.p +0 −20
  647. sys/src/games/festoon.c +0 −1661
  648. sys/src/games/gb/apu.c +0 −484
  649. sys/src/games/gb/cpu.c +0 −554
  650. sys/src/games/gb/dat.h +0 −160
  651. sys/src/games/gb/ev.c +0 −123
  652. sys/src/games/gb/fns.h +0 −28
  653. sys/src/games/gb/gb.c +0 −491
  654. sys/src/games/gb/mem.c +0 −590
  655. sys/src/games/gb/mkfile +0 −16
  656. sys/src/games/gb/ppu.c +0 −341
  657. sys/src/games/gb/state.c +0 −164
  658. sys/src/games/gba/apu.c +0 −379
  659. sys/src/games/gba/cpu.c +0 −1284
  660. sys/src/games/gba/dat.h +0 −156
  661. sys/src/games/gba/ev.c +0 −226
  662. sys/src/games/gba/fns.h +0 −28
  663. sys/src/games/gba/gba.c +0 −474
  664. sys/src/games/gba/mem.c +0 −639
  665. sys/src/games/gba/mkfile +0 −16
  666. sys/src/games/gba/ppu.c +0 −795
  667. sys/src/games/gba/state.c +0 −165
  668. sys/src/games/geigerstats.c +0 −90
  669. sys/src/games/glendy.c +0 −531
  670. sys/src/games/juggle.c +0 −217
  671. sys/src/games/life.c +0 −446
  672. sys/src/games/mahjongg/graphics.c +0 −334
  673. sys/src/games/mahjongg/level.c +0 −149
  674. sys/src/games/mahjongg/logic.c +0 −99
  675. sys/src/games/mahjongg/mahjongg.c +0 −233
  676. sys/src/games/mahjongg/mahjongg.h +0 −114
  677. sys/src/games/mahjongg/mkfile +0 −20
  678. sys/src/games/mandel.c +0 −238
  679. sys/src/games/md/cpu.c +0 −1181
  680. sys/src/games/md/dat.h +0 −97
  681. sys/src/games/md/fns.h +0 −20
  682. sys/src/games/md/md.c +0 −341
  683. sys/src/games/md/mem.c +0 −437
  684. sys/src/games/md/mkfile +0 −15
  685. sys/src/games/md/vdp.c +0 −397
  686. sys/src/games/md/ym.c +0 −454
  687. sys/src/games/md/z80.c +0 −821
  688. sys/src/games/memo.c +0 −392
  689. sys/src/games/midi.c +0 −250
  690. sys/src/games/mines/LICENCE +0 −340
  691. sys/src/games/mines/README +0 −31
  692. sys/src/games/mines/digit0.c +0 −70
  693. sys/src/games/mines/digit0.h +0 −23
  694. sys/src/games/mines/digit1.c +0 −70
  695. sys/src/games/mines/digit1.h +0 −23
  696. sys/src/games/mines/digit2.c +0 −70
  697. sys/src/games/mines/digit2.h +0 −23
  698. sys/src/games/mines/digit3.c +0 −70
  699. sys/src/games/mines/digit3.h +0 −23
  700. sys/src/games/mines/digit4.c +0 −70
  701. sys/src/games/mines/digit4.h +0 −23
  702. sys/src/games/mines/digit5.c +0 −70
  703. sys/src/games/mines/digit5.h +0 −23
  704. sys/src/games/mines/digit6.c +0 −70
  705. sys/src/games/mines/digit6.h +0 −23
  706. sys/src/games/mines/digit7.c +0 −70
  707. sys/src/games/mines/digit7.h +0 −23
  708. sys/src/games/mines/digit8.c +0 −70
  709. sys/src/games/mines/digit8.h +0 −23
  710. sys/src/games/mines/digit9.c +0 −70
  711. sys/src/games/mines/digit9.h +0 −23
  712. sys/src/games/mines/empty0.c +0 −69
  713. sys/src/games/mines/empty0.h +0 −23
  714. sys/src/games/mines/empty1.c +0 −69
  715. sys/src/games/mines/empty1.h +0 −23
  716. sys/src/games/mines/empty2.c +0 −69
  717. sys/src/games/mines/empty2.h +0 −23
  718. sys/src/games/mines/empty3.c +0 −69
  719. sys/src/games/mines/empty3.h +0 −23
  720. sys/src/games/mines/empty4.c +0 −69
  721. sys/src/games/mines/empty4.h +0 −23
  722. sys/src/games/mines/empty5.c +0 −69
  723. sys/src/games/mines/empty5.h +0 −23
  724. sys/src/games/mines/empty6.c +0 −69
  725. sys/src/games/mines/empty6.h +0 −23
  726. sys/src/games/mines/empty7.c +0 −69
  727. sys/src/games/mines/empty7.h +0 −23
  728. sys/src/games/mines/empty8.c +0 −69
  729. sys/src/games/mines/empty8.h +0 −23
  730. sys/src/games/mines/explosion.c +0 −69
  731. sys/src/games/mines/explosion.h +0 −23
  732. sys/src/games/mines/fault.c +0 −69
  733. sys/src/games/mines/fault.h +0 −23
  734. sys/src/games/mines/game.c +0 −144
  735. sys/src/games/mines/game.h +0 −23
  736. sys/src/games/mines/mark.c +0 −69
  737. sys/src/games/mines/mark.h +0 −23
  738. sys/src/games/mines/mined.c +0 −69
  739. sys/src/games/mines/mined.h +0 −23
  740. sys/src/games/mines/mines.c +0 −764
  741. sys/src/games/mines/mkfile +0 −61
  742. sys/src/games/mines/mouse.c +0 −69
  743. sys/src/games/mines/mouse.h +0 −23
  744. sys/src/games/mines/move.c +0 −144
  745. sys/src/games/mines/move.h +0 −23
  746. sys/src/games/mines/oops.c +0 −144
  747. sys/src/games/mines/oops.h +0 −23
  748. sys/src/games/mines/pictures/digit0.raw +0 −0
  749. sys/src/games/mines/pictures/digit1.raw +0 −0
  750. sys/src/games/mines/pictures/digit2.raw +0 −0
  751. sys/src/games/mines/pictures/digit3.raw +0 −0
  752. sys/src/games/mines/pictures/digit4.raw +0 −0
  753. sys/src/games/mines/pictures/digit5.raw +0 −0
  754. sys/src/games/mines/pictures/digit6.raw +0 −0
  755. sys/src/games/mines/pictures/digit7.raw +0 −0
  756. sys/src/games/mines/pictures/digit8.raw +0 −0
  757. sys/src/games/mines/pictures/digit9.raw +0 −0
  758. sys/src/games/mines/pictures/empty0.raw +0 −1
  759. sys/src/games/mines/pictures/empty1.raw +0 −0
  760. sys/src/games/mines/pictures/empty2.raw +0 −0
  761. sys/src/games/mines/pictures/empty3.raw +0 −0
  762. sys/src/games/mines/pictures/empty4.raw +0 −0
  763. sys/src/games/mines/pictures/empty5.raw +0 −0
  764. sys/src/games/mines/pictures/empty6.raw +0 −0
  765. sys/src/games/mines/pictures/empty7.raw +0 −0
  766. sys/src/games/mines/pictures/empty8.raw +0 −0
  767. sys/src/games/mines/pictures/explosion.raw +0 −0
  768. sys/src/games/mines/pictures/fault.raw +0 −0
  769. sys/src/games/mines/pictures/game.raw +0 −0
  770. sys/src/games/mines/pictures/mark.raw +0 −0
  771. sys/src/games/mines/pictures/mined.raw +0 −0
  772. sys/src/games/mines/pictures/mouse.raw +0 −0
  773. sys/src/games/mines/pictures/move.raw +0 −0
  774. sys/src/games/mines/pictures/oops.raw +0 −0
  775. sys/src/games/mines/pictures/push.raw +0 −0
  776. sys/src/games/mines/pictures/query.raw +0 −0
  777. sys/src/games/mines/pictures/sign.raw +0 −0
  778. sys/src/games/mines/pictures/unknown.raw +0 −1
  779. sys/src/games/mines/pictures/win.raw +0 −0
  780. sys/src/games/mines/push.c +0 −144
  781. sys/src/games/mines/push.h +0 −23
  782. sys/src/games/mines/query.c +0 −69
  783. sys/src/games/mines/query.h +0 −23
  784. sys/src/games/mines/sign.c +0 −70
  785. sys/src/games/mines/sign.h +0 −23
  786. sys/src/games/mines/unknown.c +0 −69
  787. sys/src/games/mines/unknown.h +0 −23
  788. sys/src/games/mines/win.c +0 −144
  789. sys/src/games/mines/win.h +0 −23
  790. sys/src/games/mkfile +0 −69
  791. sys/src/games/mole.c +0 −249
  792. sys/src/games/music/Readme +0 −12
  793. sys/src/games/music/debug.h +0 −13
  794. sys/src/games/music/icon/next.bit +0 −0
  795. sys/src/games/music/icon/pause.bit +0 −0
  796. sys/src/games/music/icon/play.bit +0 −0
  797. sys/src/games/music/icon/prev.bit +0 −0
  798. sys/src/games/music/icon/question.bit +0 −0
  799. sys/src/games/music/icon/root.bit +0 −0
  800. sys/src/games/music/icon/skull.bit +0 −0
  801. sys/src/games/music/icon/stop.bit +0 −0
  802. sys/src/games/music/icon/trash.bit +0 −0
  803. sys/src/games/music/juke.rc +0 −57
  804. sys/src/games/music/jukebox/client.c +0 −157
  805. sys/src/games/music/jukebox/client.h +0 −10
  806. sys/src/games/music/jukebox/colors.c +0 −120
  807. sys/src/games/music/jukebox/colors.h +0 −30
  808. sys/src/games/music/jukebox/mk.dep +0 −4
  809. sys/src/games/music/jukebox/mkfile +0 −16
  810. sys/src/games/music/jukebox/music.c +0 −1091
  811. sys/src/games/music/jukebox/playlist.c +0 −297
  812. sys/src/games/music/jukebox/playlist.h +0 −26
  813. sys/src/games/music/jukefs/catset.c +0 −152
  814. sys/src/games/music/jukefs/catset.h +0 −8
  815. sys/src/games/music/jukefs/fs.c +0 −757
  816. sys/src/games/music/jukefs/mk.dep +0 −6
  817. sys/src/games/music/jukefs/mkfile +0 −18
  818. sys/src/games/music/jukefs/object.h +0 −117
  819. sys/src/games/music/jukefs/parse.c +0 −616
  820. sys/src/games/music/jukefs/parse.h +0 −15
  821. sys/src/games/music/jukefs/print.c +0 −489
  822. sys/src/games/music/jukefs/print.h +0 −6
  823. sys/src/games/music/jukefs/search.c +0 −44
  824. sys/src/games/music/jukefs/search.h +0 −5
  825. sys/src/games/music/jukefs/server.c +0 −214
  826. sys/src/games/music/mkfile +0 −51
  827. sys/src/games/music/mkinc +0 −9
  828. sys/src/games/music/playlistfs/boilerplate.c +0 −100
  829. sys/src/games/music/playlistfs/fs.c +0 −892
  830. sys/src/games/music/playlistfs/main.c +0 −94
  831. sys/src/games/music/playlistfs/mk.dep +0 −5
  832. sys/src/games/music/playlistfs/mkfile +0 −16
  833. sys/src/games/music/playlistfs/player.c +0 −373
  834. sys/src/games/music/playlistfs/playlist.h +0 −147
  835. sys/src/games/music/playlistfs/playplumb.c +0 −20
  836. sys/src/games/music/playlistfs/volume.c +0 −91
  837. sys/src/games/music/readcd +0 −46
  838. sys/src/games/nes/apu.c +0 −309
  839. sys/src/games/nes/cpu.c +0 −453
  840. sys/src/games/nes/dat.h +0 −108
  841. sys/src/games/nes/fns.h +0 −16
  842. sys/src/games/nes/joynes +0 −33
  843. sys/src/games/nes/mem.c +0 −557
  844. sys/src/games/nes/mkfile +0 −15
  845. sys/src/games/nes/nes.c +0 −337
  846. sys/src/games/nes/ppu.c +0 −344
  847. sys/src/games/nes/state.c +0 −145
  848. sys/src/games/packet.c +0 −435
  849. sys/src/games/snes/cpu.c +0 −1052
  850. sys/src/games/snes/dat.h +0 −84
  851. sys/src/games/snes/dsp.c +0 −647
  852. sys/src/games/snes/fns.h +0 −30
  853. sys/src/games/snes/mem.c +0 −655
  854. sys/src/games/snes/mkfile +0 −16
  855. sys/src/games/snes/ppu.c +0 −954
  856. sys/src/games/snes/snes.c +0 −412
  857. sys/src/games/snes/spc.c +0 −748
  858. sys/src/games/snes/state.c +0 −194
  859. sys/src/games/sokoban/README +0 −22
  860. sys/src/games/sokoban/animation.c +0 −60
  861. sys/src/games/sokoban/graphics.c +0 −124
  862. sys/src/games/sokoban/level.c +0 −101
  863. sys/src/games/sokoban/mkfile +0 −21
  864. sys/src/games/sokoban/move.c +0 −136
  865. sys/src/games/sokoban/route.c +0 −280
  866. sys/src/games/sokoban/sokoban.c +0 −378
  867. sys/src/games/sokoban/sokoban.h +0 −119
  868. sys/src/games/sudoku/game.c +0 −436
  869. sys/src/games/sudoku/levels.c +0 −200
  870. sys/src/games/sudoku/mkfile +0 −18
  871. sys/src/games/sudoku/sudoku.c +0 −422
  872. sys/src/games/sudoku/sudoku.h +0 −55
  873. sys/src/games/xs.c +0 −891
  874. sys/src/games/xs.h +0 −24
  875. sys/src/mkfile +1 −1
acme/acid/Acid+6−0
@@ -0,0 +1,6 @@
1+#!/bin/rc
2+if(~ $#* 0){
3+ echo usage: Acid pid >[2=1]
4+ exit usage
5+}
6+win acid -l acme $*
acme/acid/guide+3−0
@@ -0,0 +1,3 @@
1+broke|rc kill program|rc
2+Acid pid
3+Acid -l thread -l acidfile pid
acme/bin/386/Mail+0−0

Binary file not shown.

acme/bin/386/News+0−0

Binary file not shown.

acme/bin/386/Wiki+0−0

Binary file not shown.

acme/bin/386/mkwnew+0−0

Binary file not shown.

acme/bin/386/spout+0−0

Binary file not shown.

acme/bin/386/win+0−0

Binary file not shown.

acme/bin/Battery+30−0
@@ -0,0 +1,30 @@
1+#!/bin/rc
2+
3+if(! test -f /mnt/apm/battery){
4+ echo no apm >[1=2]
5+ exit 'no apm'
6+}
7+
8+cd /mnt/acme/new
9+echo name /dev/apm >ctl
10+echo dump Battery >ctl
11+
12+awkscript='
13+NR==1 {
14+ if($3 != -1)
15+ printf("%d%% %d:%02d %s", $2, $3/3600, ($3/60)%60, $1);
16+ else
17+ printf("%d%% %s", $2, $1);
18+}
19+'
20+
21+fn chk {
22+ what=`{awk $awkscript /mnt/apm/battery}
23+ echo cleartag >ctl || exit die
24+ echo clean >ctl || exit die
25+ echo ' '^$"what >tag || exit die
26+}
27+
28+chk
29+while(sleep 60)
30+ chk
acme/bin/Isspam+13−0
@@ -0,0 +1,13 @@
1+#!/bin/rc
2+
3+if(! ~ $#* 0){
4+ echo usage: Isspam >[1=2]
5+ exit usage
6+}
7+
8+if(! ~ `{pwd} /mail/fs/*/[0-9]* || ! test -f raw || ! test -f unixheader){
9+ echo must run in mail directory >[1=2]
10+ exit 'bad dir'
11+}
12+
13+cat unixheader raw | upas/isspam
acme/bin/Mail+9−0
@@ -0,0 +1,9 @@
1+#!/bin/rc
2+
3+#/mail/fs is read-protected unless fs is mounted
4+test -r /mail/fs || {
5+ if(test -d /mnt/term/mail/fs/mbox) bind /mnt/term/mail/fs /mail/fs
6+ if not upas/fs
7+}
8+
9+exec /acme/bin/$objtype/Mail $*
acme/bin/Perl+7−0
@@ -0,0 +1,7 @@
1+#!/bin/rc
2+
3+# aperl:
4+# Executes perl command and alters stderr to produce Acme-friendly error messages
5+# Created 02-JUL-1996, Luther Huffman, lutherh@stratcom.com
6+
7+/bin/perl $* |[2] /bin/perl -pe 's/ line (\d+)/:$1 /' >[1=2]
acme/bin/README+3−0
@@ -0,0 +1,3 @@
1+The source directory should be called ./src instead of ./source,
2+but this directory is bound into /bin and there is a command called
3+src that the local directory would hide.
acme/bin/Spam+13−0
@@ -0,0 +1,13 @@
1+#!/bin/rc
2+
3+if(! ~ $#* 0){
4+ echo usage: Spam >[1=2]
5+ exit usage
6+}
7+
8+if(! ~ `{pwd} /mail/fs/*/[0-9]* || ! test -f raw || ! test -f unixheader){
9+ echo must run in mail directory >[1=2]
10+ exit 'bad dir'
11+}
12+
13+cat unixheader raw | upas/spam
acme/bin/Unspam+13−0
@@ -0,0 +1,13 @@
1+#!/bin/rc
2+
3+if(! ~ $#* 0){
4+ echo usage: Unspam >[1=2]
5+ exit usage
6+}
7+
8+if(! ~ `{pwd} /mail/fs/*/[0-9]* || ! test -f raw || ! test -f unixheader){
9+ echo must run in mail directory >[1=2]
10+ exit 'bad dir'
11+}
12+
13+cat unixheader raw | upas/unspam
acme/bin/adiff+24−0
@@ -0,0 +1,24 @@
1+#!/bin/rc
2+
3+if(~ $#* 0 1){
4+ echo >[1=2] usage: adiff file1 file2
5+ echo >[1=2] or adiff file1 file2... dir
6+ exit usage
7+}
8+
9+dir = /mnt/wsys
10+if(! test -f $dir/cons)
11+ dir = /mnt/term/$dir
12+id=`{cat $dir/new/ctl}
13+id=$id(1)
14+
15+l=$1
16+r=$2
17+if (test -d $1) l=$1/`{basename $2}
18+if not if (test -d $2) r=$2/`{basename $1}
19+
20+echo 'name '^`{pwd}^/-diff-^`{basename $l} > $dir/$id/ctl
21+
22+diff $* | awk -v 'l='$l -v 'r='^$r '/^diff/ {l=$2; r=$3; next} /^[1-9]/ {sub("[acd]", " & " r ":"); sub("^", l ":", $0)}
23+ {print $0}' > $dir/$id/body
24+echo clean > $dir/$id/ctl
acme/bin/agrep+3−0
@@ -0,0 +1,3 @@
1+#!/bin/rc
2+
3+exec grep -n $* /dev/null
acme/bin/amd64/Mail+0−0

Binary file not shown.

acme/bin/amd64/News+0−0

Binary file not shown.

acme/bin/amd64/Wiki+0−0

Binary file not shown.

acme/bin/amd64/mkwnew+0−0

Binary file not shown.

acme/bin/amd64/spout+0−0

Binary file not shown.

acme/bin/amd64/win+0−0

Binary file not shown.

acme/bin/ap+12−0
@@ -0,0 +1,12 @@
1+#!/bin/rc
2+args=''
3+while(~ $1 -*) {
4+ args=$args^' '^$1
5+ shift 1
6+}
7+if (~ $#1 0)
8+ sysname=alice
9+if not
10+ sysname=$1
11+if (! test -f /n/$sysname/usr/spool/ap ) { 9fs $sysname }
12+eval exec /acme/bin/$cputype/apread $args $sysname
acme/bin/aspell+43−0
@@ -0,0 +1,43 @@
1+#!/bin/rc
2+
3+spellflags=()
4+fflag=''
5+for(x){
6+ switch($x){
7+ case -[bcvx]
8+ spellflags=($spellflags $x)
9+ case -f
10+ fflag=$x
11+ case *
12+ if(~ $fflag -f) {
13+ spellflags=($spellflags -f $x)
14+ fflag=''
15+ }
16+ if not args = ($args $x)
17+ }
18+}
19+
20+dir = /mnt/wsys
21+if(! test -f $dir/cons)
22+ dir = /mnt/term/$dir
23+id=`{cat $dir/new/ctl}
24+id=$id(1)
25+
26+if(~ $#args 1 && ~ $args /*){
27+ adir = `{basename -d $args}
28+ args = `{basename $args}
29+ echo 'name '^$adir^/-spell > $dir/$id/ctl
30+ cd $adir
31+}
32+if not {
33+ echo 'name '^`{pwd}^/-spell > $dir/$id/ctl
34+}
35+
36+{
37+ echo noscroll
38+ if(~ $#args 0)
39+ /acme/bin/$cputype/spout | sort -t: -u +2 | sort -t: +1.1n | aux/sprog -a $spellflags > $dir/$id/body
40+ if not for(i in $args)
41+ /acme/bin/$cputype/spout $i | sort -t: -u +2 | sort -t: +1.1n | aux/sprog -a $spellflags > $dir/$id/body
42+ echo clean
43+}> $dir/$id/ctl
acme/bin/guide+4−0
@@ -0,0 +1,4 @@
1+win
2+aspell file
3+adiff file1 file2
4+adict -d oed
acme/bin/ind+3−0
@@ -0,0 +1,3 @@
1+#!/bin/rc
2+
3+sed 's/^/ /' $*
acme/bin/new+10−0
@@ -0,0 +1,10 @@
1+#!/bin/rc
2+
3+id=`{cat /mnt/acme/new/ctl}
4+id=$id(1)
5+cmd = $*
6+if(~ $#cmd 0) cmd = cat
7+
8+echo 'name '^`{pwd}^/-^`{basename $cmd(1)} > /mnt/acme/$id/ctl
9+$cmd > /mnt/acme/$id/body
10+echo clean > /mnt/acme/$id/ctl
acme/bin/quote+3−0
@@ -0,0 +1,3 @@
1+#!/bin/rc
2+
3+sed 's/^/> /' $*
acme/bin/source/6.mkwnew+0−0

Binary file not shown.

acme/bin/source/6.spout+0−0

Binary file not shown.

acme/bin/source/8.mkwnew+0−0

Binary file not shown.

acme/bin/source/8.spout+0−0

Binary file not shown.

acme/bin/source/acd/README+33−0
@@ -0,0 +1,33 @@
1+This is a CD player for use under Acme.
2+
3+It is derived from my earlier cdplay, which
4+was in turn derived from a 2nd edition player
5+called vcd. I think hardly any of the code from
6+vcd is left anymore, but it's what got me started.
7+Vcd was originally by David Hogan with additions
8+by Alberto Nava. David Hogan claims the only
9+code left is the definition of struct Msf.
10+
11+Run it by executing "acd /dev/sdD0", where
12+/dev/sdD0 is your CD reader.
13+
14+A window with a track list will appear, with
15+tracks named Track 1, Track 2, etc.
16+If it can be found in the freedb.org CD database,
17+real track names will replace the boring
18+ones before long.
19+
20+To start playing a track, right click the number.
21+A "> " marks the currently playing track.
22+When that track finishes, acd plays the track
23+on the next line. This means you can edit
24+the window as thought it were a play list.
25+
26+If the next line is "repeat", acd will start again
27+at the first song listed in the window.
28+
29+CD changes are handled gracefully.
30+
31+Russ Cox
32+9 August 2000
33+rsc@plan9.bell-labs.com
acme/bin/source/acd/access+243−0
@@ -0,0 +1,243 @@
1+TWO FORMS OF ACCESS TO THE FREEDB
2+---------------------------------
3+
4+In the following document we will refer to CDDB instead of freedb, since
5+from a technical point of view, freedb is a CDDB-Server as it uses the
6+CDDB-protocol.
7+
8+If you are interested in incorporating the use of freedb in your
9+software, there are two forms of access that you may consider.
10+
11+1. <a href="#local">Local access</a>
12+
13+ In this mode your software simply attempts to open local files on
14+ the computer to access the CDDB.
15+
16+2. <a href="#remote">Remote access</a>
17+
18+ In this mode the software must connect to a freedb server on the
19+ network to access the CDDB. There is a CDDB server protocol that
20+ the software (also known as the "client") must use to converse with
21+ the server.
22+
23+You may choose to support either one, or both of these modes.
24+
25+
26+CDDB DISCID
27+-----------
28+
29+Both forms of CDDB access requires that the software computes a "disc
30+ID" which is an identifier that is used to access the CDDB. The disc
31+ID is a 8-digit hexadecimal (base-16) number, computed using data from
32+a CD's Table-of-Contents (TOC) in MSF (Minute Second Frame) form. The
33+algorithm is listed below in the <a href="http://freedb.freedb.org/sections.php?op=viewarticle&artid=6">DISCID Howto</a>.
34+
35+It is crucial that your software compute the disc ID correctly. If it
36+does not generate the disc ID, it will not be compatible with the
37+CDDB. Moreover, if your software submits CDDB entries with bad disc
38+IDs to the freedb archives, it could compromise the integrity of the
39+freedb.
40+
41+If you have access to a UNIX platform that xmcd supports, we suggest
42+installing xmcd, and then test the disc ID code in your software by
43+comparing the disc ID generated by xmcd with that of your software,
44+for as large a number of CDs as possible.
45+
46+
47+<a name="local"></a>LOCAL CDDB ACCESS
48+-----------------
49+
50+There are two forms of the CDDB archive available, the standard form
51+and the alternate form. Both forms are available for download from
52+various servers. You can always find an actual list of mirrors on the
53+freedb-homepage at <a href="http://freedb.freedb.org">http://freedb.freedb.org</a>.
54+The standard form of the CDDB archive is released to the public as
55+a UNIX tar(1)-format archive, compressed with gzip. The alternate
56+form archive is in the .zip format that is popular on the Windows
57+platform.
58+
59+Standard Form:
60+--------------
61+
62+Each CD entry is a separate file in the xmcd CDDB. These files are
63+organized in several directories, each directory is a category of
64+music. Currently the "official" categories are listed as follows:
65+
66+ blues
67+ classical
68+ country
69+ data
70+ folk
71+ jazz
72+ misc
73+ newage
74+ reggae
75+ rock
76+ soundtrack
77+
78+The individual CDDB files have a file name that is the 8-digit disc
79+ID. For example, under the blues directory there may be the following
80+files:
81+
82+ 0511c012
83+ 060e7314
84+ 0c01e902
85+ 0f0c3112
86+ ...
87+ fa0f6f10
88+ fb0f8814
89+ fd0e6013
90+
91+To access the CDDB entry associated with a CD, your software simply
92+opens the appropriate file and reads the information.
93+
94+The content of each of these files is in a format described in the
95+<a href="http://freedb.freedb.org/software/old/DBFORMAT">database-format specification</a>.
96+
97+Different pressings of a particular CD title may contain differences
98+in timings that can cause the computed disc ID to be different.
99+The CDDB allows this by having multiple file names be links to
100+the same file. The links are implemented as actual filesystem links
101+(see the ln(1) command) on UNIX systems. For example, the following
102+files in the rock directory are all links to the same file, and
103+refer to the CD "Pink Floyd / The Division Bell".:
104+
105+ 850f740b
106+ 850f950b
107+ 850f970b
108+ 860f960b
109+ 890f970b
110+
111+Xmcd and the CD database server use this form of the CDDB archive. The
112+benefit of the standard form of the CDDB archive is very fast access,
113+and ease of add/delete/edit operations on entries.
114+
115+Alternate Form:
116+---------------
117+
118+Due to limitations in the FAT file system used on Windows 9x and
119+Windows ME, it is unfeasible to use the standard format CDDB archive
120+due to the large number of files. This is because such a filesystem
121+operates on fixed-size clusters and even a small file (and most CDDB
122+files are 1KB or less) would consume the space of a full cluster
123+(Depending upon disk size, a cluster can range from 4KB to 32KB in
124+size). Thus, a tremendous amount of disk space would be wasted on
125+these systems if the CDDB archive is used in its standard form.
126+
127+An alternate form of the CDDB archives was created for use by software
128+that must operate on a system with the FAT limitations.
129+
130+The alterate form still use the separate category directories as the
131+standard form, but concatenates many files into a smaller number of
132+files under each category. The first two digits of the CDDB file names
133+is used as a key for concatenation, each file is allowed to grow to
134+approximately 64KB in size before a new file is started. The file name
135+indicates what range of the digits are included in that file. For
136+example, under the blues category we may have the following files:
137+
138+ 01to36
139+ 37to55
140+ 56to71
141+ ...
142+ b2tod7
143+ d8toff
144+
145+The 01to36 file contains all CDDB entries with disc ID 01xxxxxx,
146+02xxxxxx, 03xxxxxx and so on, up to 36xxxxxx.
147+
148+Each entry in the concatenated file begins with the keyword
149+
150+#FILENAME=xxxxxxxx
151+
152+where discid is the 8-digit hexadecimal disc ID of that entry. Your
153+software must search through the appropriate file to locate the desired
154+entry. The CDDB entry is in the format described in Appendix B below.
155+
156+The alternate form avoids the problem of inefficient disk space
157+utilization on FAT-based filesystems, but is slower to access than the
158+standard form, and it is much more cumbersome to perform add/delete/edit
159+operations on a CDDB entry.
160+
161+
162+<a name="remote"></a>REMOTE CDDB ACCESS
163+------------------
164+
165+Your software must be able to communicate with a remote CD server
166+system via TCP/IP or HTTP.
167+There are a number of public freedb servers operating
168+on the Internet. The <a href="http://freedb.freedb.org/sections.php?op=viewarticle&artid=9">current list of public servers</a> is listed on the
169+freedb web page at:
170+
171+ http://freedb.freedb.org.
172+
173+It may also be obtained programmatically via the CDDB protocol "sites"
174+command.
175+
176+TCP/IP access:
177+
178+All current freedb servers answer at TCP port 888. There may be future
179+sites that deviate from this convention, however.
180+
181+HTTP access:
182+
183+The freedb-servers can be accessed via the cddb.cgi. This is resides at the
184+following path: /~cddb/cddb.cgi
185+Thus, the URL for accessing the server at freedb.freedb.org is:
186+http://freedb.freedb.org/~cddb/cddb.cgi
187+
188+You should make the freedb server host (or hosts) and port numbers
189+user-configurable in your software. Do not hard-wire the list of
190+CD database servers into your code. The list of active servers changes
191+over time.
192+
193+The CDDB server protocol is described in the <a href="http://freedb.freedb.org/sections.php?op=viewarticle&artid=28">CDDB-protocol documentation</a>.
194+
195+The CDDB entry returned from the server via a "cddb read" command is in
196+the format described <a href="http://freedb.freedb.org/software/old/DBFORMAT">database-format specification</a>.
197+
198+You may experiment with the freedb server by connecting to port 888 of
199+the server host via the "telnet" program, and then typing the cddb
200+protocol commands by hand. For example:
201+
202+ telnet freedb.freedb.org 888
203+
204+connects you to the freedb server at freedb.freedb.org.
205+
206+Some additional notes for accessing freedb over the Internet:
207+
208+Your application should always specify the highest documented protocol
209+level. The highest level currently supported is "3". Lower protocol
210+levels will work, but are only provided for compatibility with older
211+CDDB applications. If you do not use the highest available protocol
212+level, certain important features will not be available to your
213+application.
214+
215+Make sure to use the proper arguments with the "hello" command. The user
216+and hostname arguments should be that of the user's email address, not
217+some fixed hard-coded value. The application name and version should be
218+that of your application, not that of another existing application.
219+
220+We consider the use of the "cddb query" command mandatory for all CDDB
221+clients. It is not valid to issue a "cddb read" command without issuing
222+a prior "cddb query" and receiving a good response, as it may yield incorrect
223+results. In addition, it is clients should support close matches
224+(aka "fuzzy" matches, or response code 211).
225+
226+The proper way to handle multiple fuzzy matches is to present the
227+entire list of matches to the user and to let the user choose between them.
228+Matches are listed in the order of best fit for the user's disc, so they
229+should be presented to the user in the order they are listed by the server.
230+
231+The suggested algorithm for obtaining the list of server sites is
232+as follows. The application should offer to get the list from
233+freedb.freedb.org with the "sites" command the first time the user runs
234+the program. Additionally the application should provide the user with
235+some method of downloading the list on-demand.
236+
237+We do strongly suggest that you provide your users with the capability of
238+choosing freedb server sites as described above. However, for some
239+applications this may not be feasible. If you do not wish to offer this
240+functionality, you may safely hard-code "freedb.freedb.org" in your
241+application as the sole freedb site to access. This will deprive your users
242+of the option to choose a site near their locale for optimal response, but
243+that is your choice.
acme/bin/source/acd/acd.h+171−0
@@ -0,0 +1,171 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <disk.h>
5+#include <auth.h>
6+#include <fcall.h>
7+#include <thread.h>
8+#include <9p.h>
9+
10+/* acme */
11+typedef struct Event Event;
12+typedef struct Window Window;
13+
14+enum
15+{
16+ STACK = 16384,
17+ EVENTSIZE = 256,
18+ NEVENT = 5,
19+};
20+
21+struct Event
22+{
23+ int c1;
24+ int c2;
25+ int q0;
26+ int q1;
27+ int flag;
28+ int nb;
29+ int nr;
30+ char b[EVENTSIZE*UTFmax+1];
31+ Rune r[EVENTSIZE+1];
32+};
33+
34+struct Window
35+{
36+ /* file descriptors */
37+ int ctl;
38+ int event;
39+ int addr;
40+ int data;
41+ Biobuf *body;
42+
43+ /* event input */
44+ char buf[512];
45+ char *bufp;
46+ int nbuf;
47+ Event e[NEVENT];
48+
49+ int id;
50+ int open;
51+ Channel *cevent; /* chan(Event*) */
52+};
53+
54+extern Window* newwindow(void);
55+extern int winopenfile(Window*, char*);
56+extern void winopenbody(Window*, int);
57+extern void winclosebody(Window*);
58+extern void wintagwrite(Window*, char*, int);
59+extern void winname(Window*, char*);
60+extern void winwriteevent(Window*, Event*);
61+extern void winread(Window*, uint, uint, char*);
62+extern int windel(Window*, int);
63+extern void wingetevent(Window*, Event*);
64+extern void wineventproc(void*);
65+extern void winwritebody(Window*, char*, int);
66+extern void winclean(Window*);
67+extern int winselect(Window*, char*, int);
68+extern int winsetaddr(Window*, char*, int);
69+extern char* winreadbody(Window*, int*);
70+extern void windormant(Window*);
71+extern void winsetdump(Window*, char*, char*);
72+
73+extern char* readfile(char*, char*, int*);
74+extern void ctlprint(int, char*, ...);
75+extern void* emalloc(uint);
76+extern char* estrdup(char*);
77+extern char* estrstrdup(char*, char*);
78+extern char* egrow(char*, char*, char*);
79+extern char* eappend(char*, char*, char*);
80+extern void error(char*, ...);
81+extern int tokenizec(char*, char**, int, char*);
82+
83+/* cd stuff */
84+typedef struct Msf Msf; /* minute, second, frame */
85+struct Msf {
86+ int m;
87+ int s;
88+ int f;
89+};
90+
91+typedef struct Track Track;
92+struct Track {
93+ Msf start;
94+ Msf end;
95+ ulong bstart;
96+ ulong bend;
97+ char *title;
98+};
99+
100+enum {
101+ MTRACK = 64,
102+};
103+typedef struct Toc Toc;
104+struct Toc {
105+ int ntrack;
106+ int nchange;
107+ int changetime;
108+ int track0;
109+ Track track[MTRACK];
110+ char *title;
111+};
112+
113+extern int msfconv(Fmt*);
114+
115+#pragma varargck argpos error 1
116+#pragma varargck argpos ctlprint 2
117+#pragma varargck type "M" Msf
118+
119+enum { /* state */
120+ Sunknown,
121+ Splaying,
122+ Spaused,
123+ Scompleted,
124+ Serror,
125+};
126+
127+typedef struct Cdstatus Cdstatus;
128+struct Cdstatus {
129+ int state;
130+ int track;
131+ int index;
132+ Msf abs;
133+ Msf rel;
134+};
135+
136+typedef struct Drive Drive;
137+struct Drive {
138+ Window *w;
139+ Channel *cstatus; /* chan(Cdstatus) */
140+ Channel *ctocdisp; /* chan(Toc) */
141+ Channel *cdbreq; /* chan(Toc) */
142+ Channel *cdbreply; /* chan(Toc) */
143+ Scsi *scsi;
144+ Toc toc;
145+ Cdstatus status;
146+};
147+
148+int gettoc(Scsi*, Toc*);
149+void drawtoc(Window*, Drive*, Toc*);
150+void redrawtoc(Window*, Toc*);
151+void tocproc(void*); /* Drive* */
152+void cddbproc(void*); /* Drive* */
153+void cdstatusproc(void*); /* Drive* */
154+
155+extern int debug;
156+
157+#define DPRINT if(debug)fprint
158+void acmeevent(Drive*, Window*, Event*);
159+
160+int playtrack(Drive*, int, int);
161+int pause(Drive*);
162+int resume(Drive*);
163+int stop(Drive*);
164+int eject(Drive*);
165+int ingest(Drive*);
166+
167+int markplay(Window*, ulong);
168+int setplaytime(Window*, char*);
169+void advancetrack(Drive*, Window*);
170+
171+
acme/bin/source/acd/acme.c+347−0
@@ -0,0 +1,347 @@
1+#include "acd.h"
2+
3+static int
4+iscmd(char *s, char *cmd)
5+{
6+ int len;
7+
8+ len = strlen(cmd);
9+ return strncmp(s, cmd, len)==0 && (s[len]=='\0' || s[len]==' ' || s[len]=='\t' || s[len]=='\n');
10+}
11+
12+static char*
13+skip(char *s, char *cmd)
14+{
15+ s += strlen(cmd);
16+ while(*s==' ' || *s=='\t' || *s=='\n')
17+ s++;
18+ return s;
19+}
20+
21+//#define PLAYSTRING "/^[0-9:]+>"
22+//#define PLAYSTRINGSPACE "/^[0-9:]+> ?"
23+//#define INITSTRING "0:00> "
24+
25+#define INITSTRING "> "
26+#define PLAYSTRING "/^>"
27+#define PLAYSTRINGSPACE "/^> ?"
28+
29+/*
30+ * find the playing string, leave in addr
31+ * if q0, q1 are non-nil, set them to the addr of the string.
32+ */
33+int
34+findplay(Window *w, char *s, ulong *q0, ulong *q1)
35+{
36+ char xbuf[25];
37+ if(w->data < 0)
38+ w->data = winopenfile(w, "data");
39+
40+ if(!winsetaddr(w, "#0", 1) || !winsetaddr(w, s, 1))
41+ return 0;
42+
43+ seek(w->addr, 0, 0);
44+ if(read(w->addr, xbuf, 24) != 24)
45+ return 0;
46+
47+ xbuf[24] = 0;
48+ if(q0)
49+ *q0 = atoi(xbuf);
50+ if(q1)
51+ *q1 = atoi(xbuf+12);
52+
53+ return 1;
54+}
55+
56+/*
57+ * find the playing string and replace the time
58+ */
59+int
60+setplaytime(Window *w, char *new)
61+{
62+ char buf[40];
63+ ulong q0, q1;
64+
65+return 1;
66+ if(!findplay(w, PLAYSTRING, &q0, &q1))
67+ return 0;
68+
69+ q1--; /* > */
70+ sprint(buf, "#%lud,#%lud", q0, q1);
71+ DPRINT(2, "setaddr %s\n", buf);
72+ if(!winsetaddr(w, buf, 1))
73+ return 0;
74+
75+ if(write(w->data, new, strlen(new)) != strlen(new))
76+ return 0;
77+
78+ return 1;
79+}
80+
81+/*
82+ * find the playing string, and remove it.
83+ * return the string at the beginning of hte next line in buf
84+ * (presumably a track number).
85+ */
86+static int
87+unmarkplay(Window *w, char *buf, int n, ulong *q0, ulong *q1, ulong *qbegin)
88+{
89+ char xbuf[24];
90+
91+ if(!findplay(w, PLAYSTRINGSPACE, q0, q1))
92+ return 0;
93+
94+ if(write(w->data, "", 0) < 0 || !winsetaddr(w, "+1+#0", 1))
95+ return 0;
96+
97+ if(qbegin) {
98+ seek(w->addr, 0, 0);
99+ if(read(w->addr, xbuf, 24) != 24)
100+ return 0;
101+ *qbegin = atoi(xbuf);
102+ }
103+
104+ if(buf) {
105+ if((n = read(w->data, buf, n-1)) < 0)
106+ return 0;
107+
108+ buf[n] = '\0';
109+ }
110+
111+ return 1;
112+}
113+
114+int
115+markplay(Window *w, ulong q0)
116+{
117+ char buf[20];
118+
119+ if(w->data < 0)
120+ w->data = winopenfile(w, "data");
121+
122+ sprint(buf, "#%lud", q0);
123+ DPRINT(2, "addr %s\n", buf);
124+ if(!winsetaddr(w, buf, 1) || !winsetaddr(w, "-0", 1))
125+ return 0;
126+ if(write(w->data, INITSTRING, strlen(INITSTRING)) != strlen(INITSTRING))
127+ return 0;
128+ return 1;
129+}
130+
131+/* return 1 if handled, 0 otherwise */
132+int
133+cdcommand(Window *w, Drive *d, char *s)
134+{
135+ s = skip(s, "");
136+
137+ if(iscmd(s, "Del")){
138+ if(windel(w, 0))
139+ threadexitsall(nil);
140+ return 1;
141+ }
142+ if(iscmd(s, "Stop")){
143+ unmarkplay(w, nil, 0, nil, nil, nil);
144+ stop(d);
145+ return 1;
146+ }
147+ if(iscmd(s, "Eject")){
148+ unmarkplay(w, nil, 0, nil, nil, nil);
149+ eject(d);
150+ return 1;
151+ }
152+ if(iscmd(s, "Ingest")){
153+ unmarkplay(w, nil, 0, nil, nil, nil);
154+ ingest(d);
155+ return 1;
156+ }
157+ if(iscmd(s, "Pause")){
158+ pause(d);
159+ return 1;
160+ }
161+ if(iscmd(s, "Resume")){
162+ resume(d);
163+ return 1;
164+ }
165+ return 0;
166+}
167+
168+void
169+drawtoc(Window *w, Drive *d, Toc *t)
170+{
171+ int i, playing;
172+
173+ if(w->data < 0)
174+ w->data = winopenfile(w, "data");
175+ if(!winsetaddr(w, ",", 1))
176+ return;
177+
178+ fprint(w->data, "Title\n\n");
179+ playing = -1;
180+ if(d->status.state == Splaying || d->status.state == Spaused)
181+ playing = d->status.track-t->track0;
182+
183+ for(i=0; i<t->ntrack; i++)
184+ fprint(w->data, "%s%d/ Track %d\n", i==playing ? "> " : "", i+1, i+1);
185+ fprint(w->data, "");
186+}
187+
188+void
189+redrawtoc(Window *w, Toc *t)
190+{
191+ int i;
192+ char old[50];
193+
194+ if(w->data < 0)
195+ w->data = winopenfile(w, "data");
196+ if(t->title) {
197+ if(winsetaddr(w, "/Title", 1))
198+ write(w->data, t->title, strlen(t->title));
199+ }
200+ for(i=0; i<t->ntrack; i++) {
201+ if(t->track[i].title) {
202+ sprint(old, "/Track %d", i+1);
203+ if(winsetaddr(w, old, 1))
204+ write(w->data, t->track[i].title, strlen(t->track[i].title));
205+ }
206+ }
207+}
208+
209+void
210+advancetrack(Drive *d, Window *w)
211+{
212+ int n;
213+ ulong q0, q1, qnext;
214+ char buf[20];
215+
216+ q0 = q1 = 0;
217+ if(!unmarkplay(w, buf, sizeof(buf), &q0, &q1, &qnext)) {
218+ DPRINT(2, "unmark: %r\n");
219+ return;
220+ }
221+
222+ DPRINT(2, "buf: %s\n", buf);
223+ if(strncmp(buf, "repeat", 6) == 0) {
224+ if(!winsetaddr(w, "#0", 1) || !findplay(w, "/^[0-9]+\\/", &qnext, nil)) {
225+ DPRINT(2, "set/find: %r\n");
226+ return;
227+ }
228+ if(w->data < 0)
229+ w->data = winopenfile(w, "data");
230+ if((n = read(w->data, buf, sizeof(buf)-1)) <= 0) {
231+ DPRINT(2, "read %d: %r\n", n);
232+ return;
233+ }
234+ buf[n] = 0;
235+ DPRINT(2, "buf: %s\n", buf);
236+ }
237+
238+ if((n = atoi(buf)) == 0)
239+ return;
240+
241+ if(!markplay(w, qnext))
242+ DPRINT(2, "err: %r");
243+
244+ playtrack(d, n-1, n-1);
245+}
246+
247+void
248+acmeevent(Drive *d, Window *w, Event *e)
249+{
250+ Event *ea, *e2, *eq;
251+ char *s, *t, *buf;
252+ int n, na;
253+ ulong q0, q1;
254+
255+ switch(e->c1){ /* origin of action */
256+ default:
257+ Unknown:
258+ fprint(2, "unknown message %c%c\n", e->c1, e->c2);
259+ break;
260+
261+ case 'E': /* write to body or tag; can't affect us */
262+ break;
263+
264+ case 'F': /* generated by our actions; ignore */
265+ break;
266+
267+ case 'K': /* type away; we don't care */
268+ break;
269+
270+ case 'M': /* mouse event */
271+ switch(e->c2){ /* type of action */
272+ case 'x': /* mouse: button 2 in tag */
273+ case 'X': /* mouse: button 2 in body */
274+ ea = nil;
275+ // e2 = nil;
276+ s = e->b;
277+ if(e->flag & 2){ /* null string with non-null expansion */
278+ e2 = recvp(w->cevent);
279+ if(e->nb==0)
280+ s = e2->b;
281+ }
282+ if(e->flag & 8){ /* chorded argument */
283+ ea = recvp(w->cevent); /* argument */
284+ na = ea->nb;
285+ recvp(w->cevent); /* ignore origin */
286+ }else
287+ na = 0;
288+
289+ /* append chorded arguments */
290+ if(na){
291+ t = emalloc(strlen(s)+1+na+1);
292+ sprint(t, "%s %s", s, ea->b);
293+ s = t;
294+ }
295+ /* if it's a known command, do it */
296+ /* if it's a long message, it can't be for us anyway */
297+ DPRINT(2, "exec: %s\n", s);
298+ if(!cdcommand(w, d, s)) /* send it back */
299+ winwriteevent(w, e);
300+ if(na)
301+ free(s);
302+ break;
303+
304+ case 'l': /* mouse: button 3 in tag */
305+ case 'L': /* mouse: button 3 in body */
306+ // buf = nil;
307+ eq = e;
308+ if(e->flag & 2){
309+ e2 = recvp(w->cevent);
310+ eq = e2;
311+ }
312+ s = eq->b;
313+ if(eq->q1>eq->q0 && eq->nb==0){
314+ buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
315+ winread(w, eq->q0, eq->q1, buf);
316+ s = buf;
317+ }
318+ DPRINT(2, "load %s\n", s);
319+ if((n = atoi(s)) != 0) {
320+ DPRINT(2, "mark %d\n", n);
321+ q0 = q1 = 0;
322+ unmarkplay(w, nil, 0, &q0, &q1, nil);
323+
324+ /* adjust eq->q* for deletion */
325+ if(eq->q0 > q1) {
326+ eq->q0 -= (q1-q0);
327+ eq->q1 -= (q1-q0);
328+ }
329+ if(!markplay(w, eq->q0))
330+ DPRINT(2, "err: %r\n");
331+
332+ playtrack(d, n-1, n-1);
333+ } else
334+ winwriteevent(w, e);
335+ break;
336+
337+ case 'i': /* mouse: text inserted in tag */
338+ case 'I': /* mouse: text inserted in body */
339+ case 'd': /* mouse: text deleted from tag */
340+ case 'D': /* mouse: text deleted from body */
341+ break;
342+
343+ default:
344+ goto Unknown;
345+ }
346+ }
347+}
acme/bin/source/acd/cddb+206−0
@@ -0,0 +1,206 @@
1+<html><html>
2+<head>
3+<title>::freedb.org::</title>
4+</head>
5+
6+<body bgcolor="#FFFFFF" text="#000000" link="#101070" vlink="#101070">
7+
8+<center>
9+
10+<table cellpadding=0 cellspacing=0 border=0 width="99%" align=center><tr><td align=left>
11+<a href="/">
12+<table border=0>
13+<td bgcolor="#ffffff">
14+ <table border=0 width=100% cellpadding=0 cellspacing=0>
15+ <td bgcolor=#101070>
16+ <table border=0>
17+ <td bgcolor=#ffffff><font face="Arial,Helvetica,Lucida" color="#101070" size=8><b>freedb</b></td>
18+ <td bgcolor=#101070><font face="Arial,Helvetica,Lucida" color="#ffffff" size=8><b>.org</b></td>
19+ </table>
20+ </td>
21+ <tr>
22+ <td align=right><font face="Arial,Helvetica,Lucida" color="#101070" size=2><b>a free approach to cddbp
23+ </table>
24+</td>
25+</table>
26+</a>
27+</td><td align=right width=100%>
28+ <form action="search.php" method=post>
29+ <font face=Arial,Helvetica size=2><input type=name name=query width=20 size=20 length=20>
30+ </td>
31+ <td align=right>&nbsp;&nbsp;<input type=image src=images/menu/english/search.gif border=0 align=middle></td>
32+ </form>
33+
34+</td></tr></table><br>
35+<table cellpadding=0 cellspacing=0 border=0 width="99%" bgcolor=101070><tr><td>
36+<table cellpadding=5 cellspacing=1 border=0 width="100%" bgcolor=FFFFFF><tr><td>
37+<font face=Lucida,Verdana,Arial,Helvetica size=2>freedb.org - a free approach to cddbp</td></tr></table></td></tr></table><P>
38+
39+<table width="99%" align=center cellpadding=0 cellspacing=0 border=0><tr>
40+ <td valign=top rowspan=5>
41+
42+<table border=0><tr><td>
43+
44+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
45+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
46+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
47+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Main Menu</B></font></td>
48+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
49+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
50+ </tr></table>
51+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
52+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
53+ <tr bgcolor="#ffffff">
54+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
55+ <td width="100%">
56+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
57+ <td><font face="verdana,helvetica,arial" size="1">
58+ <li><a href=index.php>Home</a>
59+<li><a href=topics.php>News-Topics</a>
60+<li><a href=sections.php?op=listarticles&secid=1>About</a>
61+<li><a href=sections.php?op=listarticles&secid=2>Developers</a>
62+<li><a href=sections.php?op=listarticles&secid=3>Applications</a>
63+<li><a href=sections.php?op=listarticles&secid=7>Download</a>
64+<li><a href=forum/index.php>Forum</a>
65+<li><a href=http://freedb.music.sk/search/>Web-based Search</a>
66+<li><a href=links.php>Web Links</a>
67+<li><a href=user.php>Your Account</a>
68+<li><a href=submit.php>Submit News</a>
69+
70+ </font></td>
71+ </tr></table>
72+
73+
74+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
75+ </tr>
76+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
77+ </table>
78+ </td>
79+
80+
81+
82+
83+
84+
85+</tr></td></table>
86+<br>
87+<table border=0><tr><td>
88+
89+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
90+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
91+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
92+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>FAQ</B></font></td>
93+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
94+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
95+ </tr></table>
96+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
97+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
98+ <tr bgcolor="#ffffff">
99+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
100+ <td width="100%">
101+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
102+ <td><font face="verdana,helvetica,arial" size="1">
103+ Our FAQ can be found <a href="http://freedb.freedb.org/sections.php?op=viewarticle&artid=26">here</a>.<br>
104+Please read the FAQ before asking questions via email. </font></td>
105+ </tr></table>
106+
107+
108+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
109+ </tr>
110+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
111+ </table>
112+ </td>
113+
114+</tr></td></table>
115+<br>
116+<table border=0><tr><td>
117+
118+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
119+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
120+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
121+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Contact</B></font></td>
122+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
123+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
124+ </tr></table>
125+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
126+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
127+ <tr bgcolor="#ffffff">
128+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
129+ <td width="100%">
130+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
131+ <td><font face="verdana,helvetica,arial" size="1">
132+ General questions:<br>
133+<a href="mailto:info@freedb.org">info@freedb.org</a><hr>
134+Databaseupdates:<br>
135+<a href="mailto:updates@freedb.org">updates@freedb.org</a><br>
136+(<b>NOT</b> for submission!)<hr>
137+Please keep in mind that we are NOT the Nero-Support and please do not send CD-submits to the adresses above.<br>
138+Submits have to go to:<br>
139+<a href="mailto:freedb-submit@freedb.org">freedb-submit@freedb.org</a> </font></td>
140+ </tr></table>
141+
142+
143+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
144+ </tr>
145+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
146+ </table>
147+ </td>
148+
149+</tr></td></table>
150+<br>
151+<table border=0><tr><td>
152+
153+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
154+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
155+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
156+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Downloads</B></font></td>
157+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
158+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
159+ </tr></table>
160+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
161+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
162+ <tr bgcolor="#ffffff">
163+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
164+ <td width="100%">
165+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
166+ <td><font face="verdana,helvetica,arial" size="1">
167+ The link to the database downloads is <a href="/sections.php?op=viewarticle&artid=12">here</a> </font></td>
168+ </tr></table>
169+
170+
171+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
172+ </tr>
173+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
174+ </table>
175+ </td>
176+
177+
178+</tr></td></table>
179+<td>&nbsp;</td><td valign="top" width="100%">
180+
181+<!-- columna de inicio -->
182+<center>
183+ <table border=0 cellpadding=1 cellspacing=0 width=100% bgcolor=000000><tr><td>
184+ <table border=0 cellpadding=8 cellspacing=0 width=100% bgcolor=FFFFFF>
185+ <tr><td align=left><font face=Arial,Helvetica size=3>
186+ <b>Database-format specification</b><br>
187+ <font size=2>
188+ <br><br>
189+ Due to problems with using backslashes on our Webpage, we cannot display the database-format specification directly here.<br>
190+But you can find it <a href="http://www.freedb.org/software/old/DBFORMAT">here</a> as a text-document.
191+ </tr></td>
192+ <tr><td align=center><font face=Arial,Helvetica>
193+ &nbsp;
194+ </tr></td>
195+ </table></tr></td></table></center></td><td>&nbsp;</td>
196+
197+
198+</tr></table></td></tr></table><br><br>
199+
200+<font face=Arial,Helvetica size=1><center>
201+<br>
202+<br>
203+<br>
204+<br>
205+</body>
206+</html>
acme/bin/source/acd/cddb.c+197−0
@@ -0,0 +1,197 @@
1+#include "acd.h"
2+#include <ctype.h>
3+
4+/* see CDDBPROTO */
5+static ulong
6+cddb_sum(int n)
7+{
8+ int ret;
9+ ret = 0;
10+ while(n > 0) {
11+ ret += n%10;
12+ n /= 10;
13+ }
14+ return ret;
15+}
16+
17+static ulong
18+diskid(Toc *t)
19+{
20+ int i, n, tmp;
21+ Msf *ms, *me;
22+
23+ n = 0;
24+ for(i=0; i < t->ntrack; i++)
25+ n += cddb_sum(t->track[i].start.m*60+t->track[i].start.s);
26+
27+ ms = &t->track[0].start;
28+ me = &t->track[t->ntrack].start;
29+ tmp = (me->m*60+me->s) - (ms->m*60+ms->s);
30+
31+ /*
32+ * the spec says n%0xFF rather than n&0xFF. it's unclear which is correct.
33+ * most CDs are in the database under both entries.
34+ */
35+ return ((n & 0xFF) << 24 | (tmp << 8) | t->ntrack);
36+}
37+
38+static void
39+append(char **d, char *s)
40+{
41+ char *r;
42+ if (*d == nil)
43+ *d = estrdup(s);
44+ else {
45+ r = emalloc(strlen(*d) + strlen(s) + 1);
46+ strcpy(r, *d);
47+ strcat(r, s);
48+ free(*d);
49+ *d = r;
50+ }
51+}
52+
53+static int
54+cddbfilltoc(Toc *t)
55+{
56+ int fd;
57+ int i;
58+ char *p, *q;
59+ Biobuf bin;
60+ Msf *m;
61+ char *f[10];
62+ int nf;
63+ char *id, *categ;
64+ char gottrack[MTRACK];
65+ int gottitle;
66+
67+ fd = dial("tcp!freedb.freedb.org!888", 0, 0, 0);
68+ if(fd < 0) {
69+ fprint(2, "cannot dial: %r\n");
70+ return -1;
71+ }
72+ Binit(&bin, fd, OREAD);
73+
74+ if((p=Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2) {
75+ died:
76+ close(fd);
77+ Bterm(&bin);
78+ fprint(2, "error talking to server\n");
79+ if(p) {
80+ p[Blinelen(&bin)-1] = 0;
81+ fprint(2, "server says: %s\n", p);
82+ }
83+ return -1;
84+ }
85+
86+ fprint(fd, "cddb hello gre plan9 9cd 1.0\r\n");
87+ if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2)
88+ goto died;
89+
90+ fprint(fd, "cddb query %8.8lux %d", diskid(t), t->ntrack);
91+ DPRINT(2, "cddb query %8.8lux %d", diskid(t), t->ntrack);
92+ for(i=0; i<t->ntrack; i++) {
93+ m = &t->track[i].start;
94+ fprint(fd, " %d", (m->m*60+m->s)*75+m->f);
95+ DPRINT(2, " %d", (m->m*60+m->s)*75+m->f);
96+ }
97+ m = &t->track[t->ntrack-1].end;
98+ fprint(fd, " %d\r\n", m->m*60+m->s);
99+ DPRINT(2, " %d\r\n", m->m*60+m->s);
100+
101+ if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2)
102+ goto died;
103+ p[Blinelen(&bin)-1] = 0;
104+ DPRINT(2, "cddb: %s\n", p);
105+ nf = tokenize(p, f, nelem(f));
106+ if(nf < 1)
107+ goto died;
108+
109+ switch(atoi(f[0])) {
110+ case 200: /* exact match */
111+ if(nf < 3)
112+ goto died;
113+ categ = f[1];
114+ id = f[2];
115+ break;
116+ case 211: /* close matches */
117+ if((p = Brdline(&bin, '\n')) == nil)
118+ goto died;
119+ if(p[0] == '.') /* no close matches? */
120+ goto died;
121+ p[Blinelen(&bin)-1] = '\0';
122+
123+ /* accept first match */
124+ nf = tokenize(p, f, nelem(f));
125+ if(nf < 2)
126+ goto died;
127+ categ = f[0];
128+ id = f[1];
129+
130+ /* snarf rest of buffer */
131+ while(p[0] != '.') {
132+ if((p = Brdline(&bin, '\n')) == nil)
133+ goto died;
134+ p[Blinelen(&bin)-1] = '\0';
135+ DPRINT(2, "cddb: %s\n", p);
136+ }
137+ break;
138+ case 202: /* no match */
139+ default:
140+ goto died;
141+ }
142+
143+ /* fetch results for this cd */
144+ fprint(fd, "cddb read %s %s\r\n", categ, id);
145+
146+ memset(gottrack, 0, sizeof(gottrack));
147+ gottitle = 0;
148+ do {
149+ if((p = Brdline(&bin, '\n')) == nil)
150+ goto died;
151+ q = p+Blinelen(&bin)-1;
152+ while(isspace(*q))
153+ *q-- = 0;
154+DPRINT(2, "cddb %s\n", p);
155+ if(strncmp(p, "DTITLE=", 7) == 0) {
156+ if (gottitle)
157+ append(&t->title, p + 7);
158+ else
159+ t->title = estrdup(p+7);
160+ gottitle = 1;
161+ } else if(strncmp(p, "TTITLE", 6) == 0 && isdigit(p[6])) {
162+ i = atoi(p+6);
163+ if(i < t->ntrack) {
164+ p += 6;
165+ while(isdigit(*p))
166+ p++;
167+ if(*p == '=')
168+ p++;
169+
170+ if (gottrack[i])
171+ append(&t->track[i].title, p);
172+ else
173+ t->track[i].title = estrdup(p);
174+ gottrack[i] = 1;
175+ }
176+ }
177+ } while(*p != '.');
178+
179+ fprint(fd, "quit\r\n");
180+ close(fd);
181+ Bterm(&bin);
182+
183+ return 0;
184+}
185+
186+void
187+cddbproc(void *v)
188+{
189+ Drive *d;
190+ Toc t;
191+
192+ threadsetname("cddbproc");
193+ d = v;
194+ while(recv(d->cdbreq, &t))
195+ if(cddbfilltoc(&t) == 0)
196+ send(d->cdbreply, &t);
197+}
acme/bin/source/acd/cddbproto+894−0
@@ -0,0 +1,894 @@
1+<html><html>
2+<head>
3+<title>::freedb.org::</title>
4+</head>
5+
6+<body bgcolor="#FFFFFF" text="#000000" link="#101070" vlink="#101070">
7+
8+<center>
9+
10+<table cellpadding=0 cellspacing=0 border=0 width="99%" align=center><tr><td align=left>
11+<a href="/">
12+<table border=0>
13+<td bgcolor="#ffffff">
14+ <table border=0 width=100% cellpadding=0 cellspacing=0>
15+ <td bgcolor=#101070>
16+ <table border=0>
17+ <td bgcolor=#ffffff><font face="Arial,Helvetica,Lucida" color="#101070" size=8><b>freedb</b></td>
18+ <td bgcolor=#101070><font face="Arial,Helvetica,Lucida" color="#ffffff" size=8><b>.org</b></td>
19+ </table>
20+ </td>
21+ <tr>
22+ <td align=right><font face="Arial,Helvetica,Lucida" color="#101070" size=2><b>a free approach to cddbp
23+ </table>
24+</td>
25+</table>
26+</a>
27+</td><td align=right width=100%>
28+ <form action="search.php" method=post>
29+ <font face=Arial,Helvetica size=2><input type=name name=query width=20 size=20 length=20>
30+ </td>
31+ <td align=right>&nbsp;&nbsp;<input type=image src=images/menu/english/search.gif border=0 align=middle></td>
32+ </form>
33+
34+</td></tr></table><br>
35+<table cellpadding=0 cellspacing=0 border=0 width="99%" bgcolor=101070><tr><td>
36+<table cellpadding=5 cellspacing=1 border=0 width="100%" bgcolor=FFFFFF><tr><td>
37+<font face=Lucida,Verdana,Arial,Helvetica size=2>freedb.org - a free approach to cddbp</td></tr></table></td></tr></table><P>
38+
39+<table width="99%" align=center cellpadding=0 cellspacing=0 border=0><tr>
40+ <td valign=top rowspan=5>
41+
42+<table border=0><tr><td>
43+
44+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
45+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
46+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
47+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Main Menu</B></font></td>
48+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
49+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
50+ </tr></table>
51+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
52+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
53+ <tr bgcolor="#ffffff">
54+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
55+ <td width="100%">
56+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
57+ <td><font face="verdana,helvetica,arial" size="1">
58+ <li><a href=index.php>Home</a>
59+<li><a href=topics.php>News-Topics</a>
60+<li><a href=sections.php?op=listarticles&secid=1>About</a>
61+<li><a href=sections.php?op=listarticles&secid=2>Developers</a>
62+<li><a href=sections.php?op=listarticles&secid=3>Applications</a>
63+<li><a href=sections.php?op=listarticles&secid=7>Download</a>
64+<li><a href=forum/index.php>Forum</a>
65+<li><a href=http://freedb.music.sk/search/>Web-based Search</a>
66+<li><a href=links.php>Web Links</a>
67+<li><a href=user.php>Your Account</a>
68+<li><a href=submit.php>Submit News</a>
69+
70+ </font></td>
71+ </tr></table>
72+
73+
74+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
75+ </tr>
76+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
77+ </table>
78+ </td>
79+
80+
81+
82+
83+
84+
85+</tr></td></table>
86+<br>
87+<table border=0><tr><td>
88+
89+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
90+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
91+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
92+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>FAQ</B></font></td>
93+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
94+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
95+ </tr></table>
96+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
97+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
98+ <tr bgcolor="#ffffff">
99+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
100+ <td width="100%">
101+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
102+ <td><font face="verdana,helvetica,arial" size="1">
103+ Our FAQ can be found <a href="http://freedb.freedb.org/sections.php?op=viewarticle&artid=26">here</a>.<br>
104+Please read the FAQ before asking questions via email. </font></td>
105+ </tr></table>
106+
107+
108+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
109+ </tr>
110+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
111+ </table>
112+ </td>
113+
114+</tr></td></table>
115+<br>
116+<table border=0><tr><td>
117+
118+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
119+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
120+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
121+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Contact</B></font></td>
122+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
123+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
124+ </tr></table>
125+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
126+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
127+ <tr bgcolor="#ffffff">
128+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
129+ <td width="100%">
130+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
131+ <td><font face="verdana,helvetica,arial" size="1">
132+ General questions:<br>
133+<a href="mailto:info@freedb.org">info@freedb.org</a><hr>
134+Databaseupdates:<br>
135+<a href="mailto:updates@freedb.org">updates@freedb.org</a><br>
136+(<b>NOT</b> for submission!)<hr>
137+Please keep in mind that we are NOT the Nero-Support and please do not send CD-submits to the adresses above.<br>
138+Submits have to go to:<br>
139+<a href="mailto:freedb-submit@freedb.org">freedb-submit@freedb.org</a> </font></td>
140+ </tr></table>
141+
142+
143+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
144+ </tr>
145+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
146+ </table>
147+ </td>
148+
149+</tr></td></table>
150+<br>
151+<table border=0><tr><td>
152+
153+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
154+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
155+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
156+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Downloads</B></font></td>
157+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
158+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
159+ </tr></table>
160+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
161+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
162+ <tr bgcolor="#ffffff">
163+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
164+ <td width="100%">
165+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
166+ <td><font face="verdana,helvetica,arial" size="1">
167+ The link to the database downloads is <a href="/sections.php?op=viewarticle&artid=12">here</a> </font></td>
168+ </tr></table>
169+
170+
171+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
172+ </tr>
173+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
174+ </table>
175+ </td>
176+
177+
178+</tr></td></table>
179+<td>&nbsp;</td><td valign="top" width="100%">
180+
181+<!-- columna de inicio -->
182+<center>
183+ <table border=0 cellpadding=1 cellspacing=0 width=100% bgcolor=000000><tr><td>
184+ <table border=0 cellpadding=8 cellspacing=0 width=100% bgcolor=FFFFFF>
185+ <tr><td align=left><font face=Arial,Helvetica size=3>
186+ <b>CDDB-protocol documentation</b><br>
187+ <font size=2>
188+ <br><br>
189+ <pre>
190+ CDDB Protocol
191+
192+ By Steve Scherf and Ti Kan
193+ --------------------------
194+
195+Revision: $Id: CDDBPROTO,v 1.6 1997/05/14 07:53:52 steve Exp steve $
196+
197+
198+Notation:
199+-&gt; : client to server
200+&lt;- : server to client
201+
202+terminating marker: `.' character in the beginning of a line
203+
204+
205+Server response code (three digit code):
206+
207+First digit:
208+1xx Informative message
209+2xx Command OK
210+3xx Command OK so far, continue
211+4xx Command OK, but cannot be performed for some specified reasons
212+5xx Command unimplemented, incorrect, or program error
213+
214+Second digit:
215+x0x Ready for further commands
216+x1x More server-to-client output follows (until terminating marker)
217+x2x More client-to-server input follows (until terminating marker)
218+x3x Connection will close
219+
220+Third digit:
221+xx[0-9] Command-specific code
222+
223+
224+CDDB Protocol Level 1:
225+----------------------
226+
227+Server sign-on banner:
228+----------------------
229+&lt;- code hostname CDDBP server version ready at date
230+
231+ code:
232+ 200 OK, read/write allowed
233+ 201 OK, read only
234+ 432 No connections allowed: permission denied
235+ 433 No connections allowed: X users allowed, Y currently active
236+ 434 No connections allowed: system load too high
237+ hostname:
238+ Server host name. Example: xyz.fubar.com
239+ version:
240+ Version number of server software. Example: v1.0PL0
241+ date:
242+ Current date and time. Example: Wed Mar 13 00:41:34 1996
243+
244+
245+Initial client-server handshake:
246+--------------------------------
247+Note: This handshake must occur before other cddb commands
248+ are accepted by the server.
249+
250+Client command:
251+-&gt; cddb hello username hostname clientname version
252+
253+ username:
254+ Login name of user. Example: johndoe
255+ hostname:
256+ Host name of client. Example: abc.fubar.com
257+ clientname:
258+ The name of the connecting client. Example: xmcd, cda, EasyCD,
259+ et cetera. Do not use the name of another client which already
260+ exists.
261+ version:
262+ Version number of client software. Example: v1.0PL0
263+
264+Server response:
265+&lt;- code hello and welcome username@hostname running clientname version
266+
267+ code:
268+ 200 Handshake successful
269+ 431 Handshake not successful, closing connection
270+ 402 Already shook hands
271+
272+
273+CDDB query:
274+-----------
275+Client command:
276+-&gt; cddb query discid ntrks off1 off2 ... nsecs
277+
278+ discid:
279+ CD disc ID number. Example: f50a3b13
280+ ntrks:
281+ Total number of tracks on CD.
282+ off1, off2, ...:
283+ Frame offset of the starting location of each track.
284+ nsecs:
285+ Total playing length of CD in seconds.
286+
287+Server response:
288+&lt;- code categ discid dtitle
289+ or
290+&lt;- code close matches found
291+&lt;- categ discid dtitle
292+&lt;- categ discid dtitle
293+&lt;- (more matches...)
294+&lt;- .
295+
296+ code:
297+ 200 Found exact match
298+ 211 Found inexact matches, list follows (until terminating marker)
299+ 202 No match found
300+ 403 Database entry is corrupt
301+ 409 No handshake
302+ categ:
303+ CD category. Example: rock
304+ discid:
305+ CD disc ID number of the found entry. Example: f50a3b13
306+ dtitle:
307+ The Disc Artist and Disc Title (The DTITLE line). For example:
308+ Pink Floyd / The Dark Side of the Moon
309+
310+
311+CDDB read:
312+----------
313+Client command:
314+-&gt; cddb read categ discid
315+
316+ categ:
317+ CD category. Example: rock
318+ discid:
319+ CD disc ID number. Example: f50a3b13
320+
321+Server response:
322+&lt;- code categ discid
323+&lt;- # xmcd 2.0 CD database file
324+&lt;- # ...
325+&lt;- (CDDB data...)
326+&lt;- .
327+ or
328+&lt;- code categ discid No such CD entry in database
329+
330+ code:
331+ 210 OK, CDDB database entry follows (until terminating marker)
332+ 401 Specified CDDB entry not found.
333+ 402 Server error.
334+ 403 Database entry is corrupt.
335+ 409 No handshake.
336+ categ:
337+ CD category. Example: rock
338+ discid:
339+ CD disc ID number. Example: f50a3b13
340+
341+
342+CDDB search: (command not yet implemented in freedb-serversoftware!)
343+------------
344+Client command:
345+-&gt; cddb srch key search_type ... search_type
346+
347+ key:
348+ Pseudo-regular expression to match. Expressions should meet the
349+ following description:
350+
351+ - No white space.
352+ - Printable characters only.
353+ - Case is ignored.
354+ search_type:
355+ CDDB fields to search through. Example: title
356+ Supported types: artist, title, extd, ext, trk
357+ categ:
358+ CD category. Example: rock
359+
360+Server response:
361+&lt;- code matches found
362+&lt;- categ discid dtitle
363+&lt;- categ discid dtitle
364+&lt;- (more matches...)
365+&lt;- .
366+
367+ code:
368+ 210 OK, matches found, list follows (until terminating marker)
369+ 401 No match found.
370+ 409 No handshake.
371+ categ:
372+ CD category. Example: rock
373+ dtitle:
374+ The Disc Artist and Disc Title (The DTITLE line). For example:
375+ Pink Floyd / The Dark Side of the Moon
376+
377+
378+CDDB write:
379+-----------
380+Client command:
381+-&gt; cddb write categ discid
382+
383+ categ:
384+ CD category. Example: rock
385+ discid:
386+ CD disc ID number. Example: f50a3b13
387+
388+Server response:
389+&lt;- code categ discid
390+
391+ code:
392+ 320 OK, input CDDB data (until terminating marker)
393+ 401 Permission denied.
394+ 402 Server file system full/file access failed.
395+ 409 No handshake.
396+ 501 Entry rejected: reason for rejection.
397+ categ:
398+ CD category. Example: rock
399+ discid:
400+ CD disc ID number. Example: f50a3b13
401+
402+Client data:
403+-&gt; # xmcd 2.0 CD database file
404+-&gt; # ...
405+-&gt; (CDDB data)
406+-&gt; .
407+
408+Server response:
409+&lt;- code message
410+
411+ code:
412+ 200 CDDB entry accepted
413+ 401 CDDB entry rejected: reason why
414+ message:
415+ Message string to indicate write status:
416+ CDDB entry accepted, or CDDB entry rejected.
417+
418+
419+Help information:
420+-----------------
421+Client command:
422+-&gt; help
423+ or
424+-&gt; help cmd
425+
426+ cmd:
427+ CDDB command. Example: quit
428+
429+ or
430+
431+-&gt; help cmd subcmd
432+
433+ cmd:
434+ CDDB command. Example: cddb
435+ subcmd:
436+ CDDB command argument. Example: query
437+
438+Server response:
439+&lt;- code Help information follows
440+&lt;- (help data ...)
441+&lt;- .
442+ or
443+&lt;- code no help information available
444+
445+ code:
446+ 210 OK, help information follows (until terminating marker)
447+ 401 No help information available
448+
449+
450+Log statistics:
451+---------------
452+Client command:
453+-&gt; log [[-l lines] [start date [end date]] | [day [days]] | [get"]]
454+
455+ lines:
456+ The maximum number of lines to print for each data list in the
457+ log statistics.
458+ start date:
459+ The date after which statistics should be calculated. Date is
460+ of the format: hh[mm[ss[MM[DD[[CC]YY]]]]]
461+
462+ E.g.: 201200053196 for 8:12 PM on May 31, 1996.
463+ 20120005312096 for 8:12 PM on May 31, 2096.
464+ 080530 for today at at 8:15 and 30 seconds.
465+
466+ If the century ("CC") is omitted, a reasonable guess is made. If
467+ this argument is omitted, all messages are considered.
468+ end date:
469+ The date after which statistics should not be calculated. If
470+ omitted, the end date is assumed to be the current date.
471+ day:
472+ The string "day". This solitary argument will cause a log search
473+ of messages generated within the last day.
474+ days:
475+ A positive numerical argument which modifies the number of days'
476+ messages to searh. If this argument is left out, the default is 1.
477+ get:
478+ The string "get". This solitary argument will cause the server
479+ to send the contents of the log file.
480+
481+Server response:
482+&lt;- code Log summary follows
483+&lt;- (log stats)
484+&lt;- .
485+ or
486+&lt;- code Log follows
487+&lt;- (log stats)
488+&lt;- .
489+
490+ code:
491+ 210 OK, log summary follows (until terminating marker)
492+ 211 OK, log follows (until terminating marker)
493+ 401 Permission denied
494+ 402 No log information available
495+ 501 Invalid start/end date
496+
497+
498+Message of the day:
499+------------------
500+Client command:
501+-&gt; motd
502+
503+Server response:
504+&lt;- code Last modified: date MOTD follows (until terminating marker)
505+&lt;- (message text)
506+&lt;- .
507+
508+ code:
509+ 210 Last modified: 05/31/96 06:31:14 MOTD follows (until terminating marker)
510+ 401 No message of the day available
511+ date:
512+ The date the text of the message of the day was modified. The date
513+ appears in the following format:
514+
515+ 05/31/96 06:31:14
516+
517+ This value may be used by client software as a message timestamp
518+ for purposes of determining if it has already been displayed. This
519+ format was chosen because it is more easily parsed than the standard
520+ ctime() format.
521+
522+
523+Server protocol level:
524+----------------------
525+Client command:
526+-&gt; proto [level]
527+
528+ level:
529+ The (numerical) protocol level to set the server to.
530+
531+Server response:
532+&lt;- code CDDB protocol level: current cur_level, supported supported_level
533+ or
534+&lt;- code OK, protocol version now: cur_level
535+
536+ code:
537+ 200 CDDB protocol level: current cur_level, supported supp_level
538+ 201 OK, protocol version now: cur_level
539+ 501 Illegal protocol level.
540+ 502 Protocol level already cur_level.
541+ cur_level:
542+ The current protocol level at which the server is running.
543+ supported_level:
544+ The maximum supported protocol level.
545+
546+
547+Server sites:
548+--------------
549+Client command:
550+-&gt; sites
551+
552+Server response:
553+&lt;- code OK, site information follows (until terminating `.')
554+&lt;- (data)
555+&lt;- .
556+
557+ code:
558+ 210 Ok, site information follows
559+ 401 No site information available.
560+
561+ The data format is as follows:
562+ site port latitude longitude description
563+
564+ The fields are as follows:
565+ site:
566+ The Internet address of the remote site.
567+ port:
568+ The port at which the server resides on that site.
569+ latitude:
570+ The latitude of the server site. The format is as follows:
571+ CDDD.MM
572+ Where "C" is the compass direction (N, S), "DDD" is the
573+ degrees, and "MM" is the minutes.
574+ longitude:
575+ The longitude of the server site. Format is as above, except
576+ the compass direction must be one of (E, W).
577+ description:
578+ A short description of the geographical location of the site.
579+
580+ Example:
581+ cddb.moonsoft.com 888 N037.23 W122.01 Fremont, CA USA
582+
583+
584+Server status:
585+--------------
586+Client command:
587+-&gt; stat
588+
589+Server response:
590+&lt;- code OK, status information follows (until terminating `.')
591+&lt;- (data)
592+&lt;- .
593+
594+ code:
595+ 210 Ok, status information follows
596+
597+ The possible data is as follows:
598+ current proto: &lt;current_level&gt;
599+ An integer representing the server's current operating protocol
600+ level.
601+ max proto: &lt;max_level&gt;
602+ The maximum supported protocol level.
603+ gets: &lt;yes | no&gt;
604+ Whether or not the client is allowed to get log information,
605+ according to the string "yes" or "no".
606+ updates: &lt;yes | no&gt;
607+ Whether or not the client is allowed to initiate a database
608+ update, according to the string "yes" or "no".
609+ posting: &lt;yes | no&gt;
610+ Whether or not the client is allowed to post new entries,
611+ according to the string "yes" or "no".
612+ quotes: &lt;yes | no&gt;
613+ Whether or not quoted arguments are enabled, according to
614+ the string "yes" or "no".
615+ current users: &lt;num_users&gt;
616+ The number of users currently connected to the server.
617+ max users: &lt;num_max_users&gt;
618+ The number of users that can concurrently connect to the server.
619+ strip ext: &lt;yes | no&gt;
620+ Whether or not extended data is stripped by the server before
621+ presented to the user.
622+ Database entries: &lt;num_db_entries&gt;
623+ The total number of entries in the database.
624+ Database entries by category:
625+ This field is followed by a list of catgories and the number
626+ of entries in that category. Each entry is of the following
627+ format:
628+
629+ &lt;white space&gt;catgory: &lt;num_db_entries&gt;
630+
631+ The list of entries is terminated by the first line that does
632+ not begin with white space.
633+
634+ Pending file transmissions:
635+ This field is followed by a list of sites that are fed new
636+ database entries at periodic intervals, and the number of
637+ entries that have yet to be transmitted to that site.
638+ Each entry is of the following format:
639+
640+ &lt;white space&gt;site: &lt;num_db_entries&gt;
641+
642+ The list of entries is terminated by the first line that does
643+ not begin with white space.
644+
645+ This list may grow as needed, so clients must expect possible
646+ unrecognizable data. Also, additional fields may be added to
647+ the currently existing lines, although no existing fields will
648+ be removed or change position.
649+
650+
651+Server version:
652+---------------
653+Client command:
654+-&gt; ver
655+
656+Server response:
657+&lt;- code servername version copyright
658+ or
659+&lt;- code Version information follows
660+
661+ code:
662+ 200 Version information.
663+ 211 OK, version information follows (until terminating marker)
664+ version:
665+ Server version. Example: v1.0PL0
666+ copyright:
667+ Copyright string. Example: Copyright (c) 1996 Steve Scherf
668+
669+
670+Database update:
671+----------------
672+Client command:
673+-&gt; update
674+
675+Server response:
676+&lt;- code Updating the database.
677+ or
678+&lt;- code Permission denied.
679+ or
680+&lt;- code Unable to update the database.
681+
682+ code:
683+ 200 Updating the database.
684+ 401 Permission denied.
685+ 402 Unable to update the database.
686+
687+
688+Server users:
689+-------------
690+Client command:
691+-&gt; whom
692+
693+Server response:
694+&lt;- code User list follows
695+
696+ code:
697+ 210 OK, user list follows (until terminating marker)
698+ 401 No user information available.
699+
700+
701+Client sign-off:
702+----------------
703+Client command:
704+-&gt; quit
705+
706+Server response:
707+&lt;- code hostname closing connection. Goodbye.
708+
709+ code:
710+ 230 OK, goodbye.
711+ hostname:
712+ Server host name. Example: xyz.fubar.com
713+
714+
715+General errors:
716+---------------
717+
718+Server response:
719+&lt;- code error
720+ code:
721+ 402 Server error.
722+ 408 CGI environment error.
723+ 500 Command syntax error, command unknown, command unimplemented.
724+ 530 Server error, server timeout.
725+
726+
727+Reserved errors:
728+----------------
729+
730+The following error codes are reserved, and will never be returned as a
731+response to a CDDB protocol command. They are intended to be used internally
732+by clients that have a need for generating pseudo-responses.
733+
734+ 600-699
735+
736+
737+CDDB Protocol Level 2:
738+----------------------
739+
740+In all respects, protocol level 2 is the same as level 1, with the exceptions
741+listed below.
742+
743+Arguments to commands may be surrounded by double quotes. All characters
744+within the quotes, including white space, are included in the argument. All
745+white space is replaced by the `_' (2Dh) character by the server. White space
746+is defined as ` ' (20h) and `^I' (control-I, or 09h).
747+
748+Arguments containing quotes that should not be interpreted with the special
749+meaning described above should be escaped with a preceding backslash character,
750+or '' (5Ch). If an actual backslash appears in an argument, it should be
751+escaped with a preceding backslash. In both cases, the preceding backslash
752+will be removed from the input before being interpreted.
753+
754+
755+CDDB Protocol Level 3:
756+----------------------
757+
758+Protocol level 3 is the same as level 2, with the exception listed below.
759+
760+The output of the "sites" command has changed to meet the folowing description:
761+
762+ The data format is as follows:
763+ site protocol port address latitude longitude description
764+
765+ The fields are as follows:
766+ site:
767+ The Internet address of the remote site.
768+ protocol:
769+ The transfer protocol used to access the site.
770+ port:
771+ The port at which the server resides on that site.
772+ address:
773+ Any additional addressing information needed to access the
774+ server. For example, for HTTP protocol servers, this would be
775+ the path to the CDDB server CGI script. This field will be
776+ "-" if no additional addressing information is needed.
777+ latitude:
778+ The latitude of the server site. The format is as follows:
779+ CDDD.MM
780+ Where "C" is the compass direction (N, S), "DDD" is the
781+ degrees, and "MM" is the minutes.
782+ longitude:
783+ The longitude of the server site. Format is as above, except
784+ the compass direction must be one of (E, W).
785+ description:
786+ A short description of the geographical location of the site.
787+
788+ Example:
789+ cddb.moonsoft.com cddbp 888 - N037.23 W122.01 Fremont, CA USA
790+ cddb.moonsoft.com http 80 /~cddb/cddb.cgi N037.23 W122.01 Fremont,CA USA
791+
792+Note that a site may appear once for each type of protocol it supports for
793+accessing the server.
794+
795+
796+Addendum A: Proper use of CDDBP:
797+--------------------------------
798+
799+There are a few guidelines that must be followed in order to make proper use
800+of CDDBP:
801+
802+- When handshaking with the server via the "cddb hello" command, the client
803+ must specify its own name and version, not that of some other client (such
804+ as xmcd). Also, the "username" and "hostname" must be that of the actual
805+ user running the program, not some hardwired value.
806+
807+- Before performing a "cddb read", the client program MUST perform a
808+ "cddb query". Failure to do so may result in the client program receiving
809+ incorrect CDDB data from the server. Also, without performing a query, the
810+ client program will not benefit from close matches in the event of the
811+ lack of an exact match in the database.
812+
813+- For accounting purposes, it is best if client programs only perform a single
814+ "cddb query" for a particular disc before performing a "cddb read" for that
815+ disc.
816+
817+
818+Addendum B: CDDBP under HTTP:
819+-----------------------------
820+
821+Accessing a server as a CGI script is done in much the same way as through
822+direct interaction. The command set is identical, though the method of
823+communication is through CDDBP commands encapsulated in the HTTP protocol.
824+The only limitation is that a single command may be executed per connection,
825+since HTTP is not truly interactive. For the server to be accessed in this
826+way, it must reside on the target host at a known URL which is accessible by
827+the host HTTP server. The client program must connect to the HTTP server on
828+the target host and issue an HTTP command with the appropriate CDDBP command
829+encapsulated within.
830+
831+Commands may be submitted to servers in CGI mode using either the "GET" or
832+"POST" HTTP commands. Both methods are supported, and there is no real
833+difference between how both are to be used other than the syntactical
834+difference between the two methods. The "POST" method may provide the ability
835+to issue longer commands, though, depending on the architecture of the system
836+on which the server resides.
837+
838+The server command must be sent as part of the "Request-URI" in the case
839+of the "GET" method, and as the "Entity-Body" in the case of the "POST"
840+method. In both cases, the command must be of the following form:
841+
842+cmd=server+command&amp;hello=joe+my.host.com+clientname+version&amp;proto=1
843+
844+Where the text following the "cmd=" represents the CDDBP command to be
845+executed, the text following the "hello=" represents the arguments to
846+the "cddb hello" command that is implied by this operation, and the
847+text following the "proto=" represents the argument to the "proto" command
848+that is implied by this operation.
849+
850+The "+" characters in the input represent spaces, and will be translated
851+by the server before performing the request. Special characters may be
852+represented by the sequence "%XX" where "XX" is a two-digit hex number
853+corresponding to the ASCII (ISO-8859-1) sequence of that character. The
854+"&amp;" characters denote separations between the command, hello and proto
855+arguments. Newlines and carriage returns must not appear anywhere in the
856+string except at the end.
857+
858+All CDDBP commands are supported under HTTP, except for "cddb hello",
859+"cddb write", "proto" and "quit".
860+
861+For example, should user "joe" on system "my.host.com" be running xmcd 2.1,
862+a read request for his currenly playing CD might look like this:
863+
864+cmd=cddb+read+rock+12345678&amp;hello=joe+my.host.com+xmcd+2.1&amp;proto=1
865+
866+The server will perform the implied "proto" and "cddb hello" commands,
867+and then perform the requested "cddb read" command.
868+
869+Server response to the command is encapsulated in the HTTP server response,
870+and appears in the "Entity-Body" exactly as it would appear using the CDDBP
871+protocol. Note that the HTTP response "Entity-Header" is not guaranteed to
872+contain a "Content-Length" field, so clients should be prepared to accept
873+variable length input. This is no different from operation under CDDBP. The
874+header will always contain a Mime "Content-Type" field which describes the
875+body of data as "text/plain".
876+
877+For more detailed information on HTTP and Mime, see RFC 1945 and RFC 1521.
878+</pre>
879+ </tr></td>
880+ <tr><td align=center><font face=Arial,Helvetica>
881+ &nbsp;
882+ </tr></td>
883+ </table></tr></td></table></center></td><td>&nbsp;</td>
884+
885+
886+</tr></table></td></tr></table><br><br>
887+
888+<font face=Arial,Helvetica size=1><center>
889+<br>
890+<br>
891+<br>
892+<br>
893+</body>
894+</html>
acme/bin/source/acd/discid+159−0
@@ -0,0 +1,159 @@
1+
2+CDDB DISCID
3+-----------
4+
5+Both forms of CDDB access require that the software compute a "disc
6+ID" which is an identifier that is used to access the CDDB. The disc
7+ID is a 8-digit hexadecimal (base-16) number, computed using data from
8+a CD's Table-of-Contents (TOC) in MSF (Minute Second Frame) form. The
9+algorithm is listed below in Appendix A.
10+
11+It is crucial that your software compute the disc ID correctly. If it
12+does not generate the correct disc ID, it will not be compatible with CDDB.
13+Moreover, if your software submits CDDB entries with bad disc IDs to the
14+CDDB archives, it could compromise the integrity of the CDDB.
15+
16+[...]
17+
18+APPENDIX A - CDDB DISCID ALGORITHM
19+----------------------------------
20+
21+The following is a C code example that illustrates how to generate the
22+CDDB disc ID. [...] A text description
23+of the algorithm follows, which should contain the necessary information
24+to code the algorithm in any programming language.
25+
26+
27+struct toc {
28+ int min;
29+ int sec;
30+ int frame;
31+};
32+
33+struct toc cdtoc[100];
34+
35+int
36+read_cdtoc_from_drive(void)
37+{
38+ /* Do whatever is appropriate to read the TOC of the CD
39+ * into the cdtoc[] structure array.
40+ */
41+ return (tot_trks);
42+}
43+
44+int
45+cddb_sum(int n)
46+{
47+ int ret;
48+
49+ /* For backward compatibility this algorithm must not change */
50+
51+ ret = 0;
52+
53+ while (n > 0) {
54+ ret = ret + (n % 10);
55+ n = n / 10;
56+ }
57+
58+ return (ret);
59+}
60+
61+unsigned long
62+cddb_discid(int tot_trks)
63+{
64+ int i,
65+ t = 0,
66+ n = 0;
67+
68+ /* For backward compatibility this algorithm must not change */
69+
70+ i = 0;
71+
72+ while (i < tot_trks) {
73+ n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec);
74+ i++;
75+ }
76+
77+ t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) -
78+ ((cdtoc[0].min * 60) + cdtoc[0].sec);
79+
80+ return ((n % 0xff) << 24 | t << 8 | tot_trks);
81+}
82+
83+main()
84+{
85+ int tot_trks;
86+
87+ tot_trks = read_cdtoc_from_drive();
88+ printf("The discid is %08x", cddb_discid(tot_trks));
89+}
90+
91+
92+This code assumes that your compiler and architecture support 32-bit
93+integers.
94+
95+The cddb_discid function computes the discid based on the CD's TOC data
96+in MSF form. The frames are ignored for this purpose. The function is
97+passed a parameter of tot_trks (which is the total number of tracks on
98+the CD), and returns the discid integer number.
99+
100+It is assumed that cdtoc[] is an array of data structures (records)
101+containing the fields min, sec and frame, which are the minute, second
102+and frame offsets (the starting location) of each track. This
103+information is read from the TOC of the CD. There are actually
104+tot_trks + 1 "active" elements in the array, the last one being the
105+offset of the lead-out (also known as track 0xAA).
106+
107+The function loops through each track in the TOC, and for each track
108+it takes the (M * 60) + S (total offset in seconds) of the track and
109+feeds it to cddb_sum() function, which simply adds the value of each digit
110+in the decimal string representation of the number. A running sum of this
111+result for each track is kept in the variable n.
112+
113+At the end of the loop:
114+1. t is calculated by subtracting the (M * 60) + S offset of the lead-out
115+minus the (M * 60) + S offset of first track (yielding the length of
116+the disc in seconds).
117+
118+2. The result of (n modulo FFh) is left-shifted by 24 bits.
119+
120+3. t is left shifted by 8.
121+
122+The bitwise-OR operation of result 2., 3. and the tot_trks number is
123+used as the discid.
124+
125+The discid is represented in hexadecimal form for the purpose of
126+xmcd cddb file names and the DISCID= field in the xmcd cddb file itself.
127+If the hexadecimal string is less than 8 characters long, it is
128+zero-padded to 8 characters (i.e., 3a8f07 becomes 003a8f07). All
129+alpha characters in the string should be in lower case, where
130+applicable.
131+
132+Important note for clients using the MS-Windows MCI interface:
133+
134+The Windows MCI interface does not provide the MSF location of the
135+lead-out. Thus, you must compute the lead-out location by taking the
136+starting position of the last track and add the length of the last track
137+to it. However, the MCI interface returns the length of the last track
138+as ONE FRAME SHORT of the actual length found in the CD's TOC. In most
139+cases this does not affect the disc ID generated, because we truncate
140+the frame count when computing the disc ID anyway. However, if the
141+lead-out track has an actual a frame count of 0, the computed quantity
142+(based on the MSF data returned from the MCI interface) would result in
143+the seconds being one short and the frame count be 74. For example,
144+a CD with the last track at an offset of 48m 32s 12f and having a
145+track length of 2m 50s 63f has a lead-out offset of 51m 23s 0f. Windows
146+MCI incorrectly reports the length as 2m 50s 62f, which would yield a
147+lead-out offset of 51m 22s 74f, which causes the resulting truncated
148+disc length to be off by one second. This will cause an incorrect disc
149+ID to be generated. You should thus add one frame to the length of the
150+last track when computing the location of the lead-out.
151+
152+The easiest way for Windows clients to compute the lead-out given information
153+in MSF format is like this:
154+
155+(offset_minutes * 60 * 75) + (offset_seconds * 75) + offset_frames +
156+(length_minutes * 60 * 75) + (length_seconds * 75) + length_frames + 1 = X
157+
158+Where X is the offset of the lead-out in frames. To find the lead-out in
159+seconds, simply divide by 75 and discard the remainder.
acme/bin/source/acd/mailinglist+220−0
@@ -0,0 +1,220 @@
1+<html><html>
2+<head>
3+<title>::freedb.org::</title>
4+</head>
5+
6+<body bgcolor="#FFFFFF" text="#000000" link="#101070" vlink="#101070">
7+
8+<center>
9+
10+<table cellpadding=0 cellspacing=0 border=0 width="99%" align=center><tr><td align=left>
11+<a href="/">
12+<table border=0>
13+<td bgcolor="#ffffff">
14+ <table border=0 width=100% cellpadding=0 cellspacing=0>
15+ <td bgcolor=#101070>
16+ <table border=0>
17+ <td bgcolor=#ffffff><font face="Arial,Helvetica,Lucida" color="#101070" size=8><b>freedb</b></td>
18+ <td bgcolor=#101070><font face="Arial,Helvetica,Lucida" color="#ffffff" size=8><b>.org</b></td>
19+ </table>
20+ </td>
21+ <tr>
22+ <td align=right><font face="Arial,Helvetica,Lucida" color="#101070" size=2><b>a free approach to cddbp
23+ </table>
24+</td>
25+</table>
26+</a>
27+</td><td align=right width=100%>
28+ <form action="search.php" method=post>
29+ <font face=Arial,Helvetica size=2><input type=name name=query width=20 size=20 length=20>
30+ </td>
31+ <td align=right>&nbsp;&nbsp;<input type=image src=images/menu/english/search.gif border=0 align=middle></td>
32+ </form>
33+
34+</td></tr></table><br>
35+<table cellpadding=0 cellspacing=0 border=0 width="99%" bgcolor=101070><tr><td>
36+<table cellpadding=5 cellspacing=1 border=0 width="100%" bgcolor=FFFFFF><tr><td>
37+<font face=Lucida,Verdana,Arial,Helvetica size=2>freedb.org - a free approach to cddbp</td></tr></table></td></tr></table><P>
38+
39+<table width="99%" align=center cellpadding=0 cellspacing=0 border=0><tr>
40+ <td valign=top rowspan=5>
41+
42+<table border=0><tr><td>
43+
44+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
45+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
46+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
47+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Main Menu</B></font></td>
48+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
49+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
50+ </tr></table>
51+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
52+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
53+ <tr bgcolor="#ffffff">
54+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
55+ <td width="100%">
56+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
57+ <td><font face="verdana,helvetica,arial" size="1">
58+ <li><a href=index.php>Home</a>
59+<li><a href=topics.php>News-Topics</a>
60+<li><a href=sections.php?op=listarticles&secid=1>About</a>
61+<li><a href=sections.php?op=listarticles&secid=2>Developers</a>
62+<li><a href=sections.php?op=listarticles&secid=3>Applications</a>
63+<li><a href=sections.php?op=listarticles&secid=7>Download</a>
64+<li><a href=forum/index.php>Forum</a>
65+<li><a href=http://freedb.music.sk/search/>Web-based Search</a>
66+<li><a href=links.php>Web Links</a>
67+<li><a href=user.php>Your Account</a>
68+<li><a href=submit.php>Submit News</a>
69+
70+ </font></td>
71+ </tr></table>
72+
73+
74+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
75+ </tr>
76+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
77+ </table>
78+ </td>
79+
80+
81+
82+
83+
84+
85+</tr></td></table>
86+<br>
87+<table border=0><tr><td>
88+
89+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
90+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
91+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
92+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>FAQ</B></font></td>
93+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
94+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
95+ </tr></table>
96+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
97+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
98+ <tr bgcolor="#ffffff">
99+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
100+ <td width="100%">
101+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
102+ <td><font face="verdana,helvetica,arial" size="1">
103+ Our FAQ can be found <a href="http://freedb.freedb.org/sections.php?op=viewarticle&artid=26">here</a>.<br>
104+Please read the FAQ before asking questions via email. </font></td>
105+ </tr></table>
106+
107+
108+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
109+ </tr>
110+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
111+ </table>
112+ </td>
113+
114+</tr></td></table>
115+<br>
116+<table border=0><tr><td>
117+
118+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
119+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
120+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
121+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Contact</B></font></td>
122+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
123+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
124+ </tr></table>
125+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
126+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
127+ <tr bgcolor="#ffffff">
128+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
129+ <td width="100%">
130+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
131+ <td><font face="verdana,helvetica,arial" size="1">
132+ General questions:<br>
133+<a href="mailto:info@freedb.org">info@freedb.org</a><hr>
134+Databaseupdates:<br>
135+<a href="mailto:updates@freedb.org">updates@freedb.org</a><br>
136+(<b>NOT</b> for submission!)<hr>
137+Please keep in mind that we are NOT the Nero-Support and please do not send CD-submits to the adresses above.<br>
138+Submits have to go to:<br>
139+<a href="mailto:freedb-submit@freedb.org">freedb-submit@freedb.org</a> </font></td>
140+ </tr></table>
141+
142+
143+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
144+ </tr>
145+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
146+ </table>
147+ </td>
148+
149+</tr></td></table>
150+<br>
151+<table border=0><tr><td>
152+
153+ <table width="115" border="0" cellpadding="0" cellspacing="0"><tr valign="top" bgcolor="#101070">
154+ <td bgcolor="#FFFFFF"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
155+ <td><img src="themes/SlashOcean/cl.gif" width="7" height="10"></td>
156+ <td><font face="verdana,helvetica,arial" size="1" color="#ffffff"><B>Downloads</B></font></td>
157+ <td align="right"><img src="themes/SlashOcean/cr.gif" width="7" height="10" alt=""></td>
158+ <td bgcolor="#FFFFFF" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3"></td>
159+ </tr></table>
160+ <table width="100%" border="0" cellpadding="0" cellspacing="0">
161+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
162+ <tr bgcolor="#ffffff">
163+ <td background="themes/SlashOcean/sl.gif"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
164+ <td width="100%">
165+ <table width="100%" border="0" cellpadding="5" cellspacing="0"><tr>
166+ <td><font face="verdana,helvetica,arial" size="1">
167+ The link to the database downloads is <a href="/sections.php?op=viewarticle&artid=12">here</a> </font></td>
168+ </tr></table>
169+
170+
171+ </td><td background="themes/SlashOcean/sr.gif" align="right"><img src="themes/SlashOcean/pix.gif" width="3" height="3" alt=""></td>
172+ </tr>
173+ <tr bgcolor="#101070"><td colspan="3"><img src="themes/SlashOcean/pix.gif" width="1" height="1"></td></tr>
174+ </table>
175+ </td>
176+
177+
178+</tr></td></table>
179+<td>&nbsp;</td><td valign="top" width="100%">
180+
181+<!-- columna de inicio -->
182+<center>
183+ <table border=0 cellpadding=1 cellspacing=0 width=100% bgcolor=000000><tr><td>
184+ <table border=0 cellpadding=8 cellspacing=0 width=100% bgcolor=FFFFFF>
185+ <tr><td align=left><font face=Arial,Helvetica size=3>
186+ <b>Mailinglists</b><br>
187+ <font size=2>
188+ <br><br>
189+ There are a couple of mailinglists available:
190+
191+<h4>fdb-apps@freedb.org</h4>
192+
193+This mailinglist is intended for all developers that want to
194+exchange tips and tricks, codesnippets and so on. Subcribe
195+to this list by sending an email to<br>
196+<a href="mailto:fdb-apps-request@freedb.org">fdb-apps-request@freedb.org</a><br>
197+with the word "subscribe" in the body of the email.
198+<h4>fdb-dev@freedb.org</h4>
199+
200+This list is for anyone interested in developing the freedb.org
201+server software. Subcribe
202+to this list by sending an email to<br>
203+<a href="mailto:fdb-dev-request@freedb.org">fdb-dev-request@freedb.org</a><br>
204+with the word "subscribe" in the body of the email.
205+ </tr></td>
206+ <tr><td align=center><font face=Arial,Helvetica>
207+ &nbsp;
208+ </tr></td>
209+ </table></tr></td></table></center></td><td>&nbsp;</td>
210+
211+
212+</tr></table></td></tr></table><br><br>
213+
214+<font face=Arial,Helvetica size=1><center>
215+<br>
216+<br>
217+<br>
218+<br>
219+</body>
220+</html>
acme/bin/source/acd/main.c+135−0
@@ -0,0 +1,135 @@
1+#include "acd.h"
2+
3+int debug;
4+
5+void
6+usage(void)
7+{
8+ fprint(2, "usage: acd dev\n");
9+ threadexitsall("usage");
10+}
11+
12+Alt
13+mkalt(Channel *c, void *v, int op)
14+{
15+ Alt a;
16+
17+ memset(&a, 0, sizeof(a));
18+ a.c = c;
19+ a.v = v;
20+ a.op = op;
21+ return a;
22+}
23+
24+void
25+freetoc(Toc *t)
26+{
27+ int i;
28+
29+ free(t->title);
30+ for(i=0; i<t->ntrack; i++)
31+ free(t->track[i].title);
32+}
33+
34+void
35+eventwatcher(Drive *d)
36+{
37+ enum { STATUS, WEVENT, TOCDISP, DBREQ, DBREPLY, NALT };
38+ Alt alts[NALT+1];
39+ Toc nt, tdb;
40+ Event *e;
41+ Window *w;
42+ Cdstatus s;
43+ char buf[40];
44+
45+ w = d->w;
46+
47+ alts[STATUS] = mkalt(d->cstatus, &s, CHANRCV);
48+ alts[WEVENT] = mkalt(w->cevent, &e, CHANRCV);
49+ alts[TOCDISP] = mkalt(d->ctocdisp, &nt, CHANRCV);
50+ alts[DBREQ] = mkalt(d->cdbreq, &tdb, CHANNOP);
51+ alts[DBREPLY] = mkalt(d->cdbreply, &nt, CHANRCV);
52+ alts[NALT] = mkalt(nil, nil, CHANEND);
53+ for(;;) {
54+ switch(alt(alts)) {
55+ case STATUS:
56+ //DPRINT(2, "s...");
57+ d->status = s;
58+ if(s.state == Scompleted) {
59+ s.state = Sunknown;
60+ advancetrack(d, w);
61+ }
62+ //DPRINT(2, "status %d %d %d %M %M\n", s.state, s.track, s.index, s.abs, s.rel);
63+ sprint(buf, "%d:%2.2d", s.rel.m, s.rel.s);
64+ setplaytime(w, buf);
65+ break;
66+ case WEVENT:
67+ //DPRINT(2, "w...");
68+ acmeevent(d, w, e);
69+ break;
70+ case TOCDISP:
71+ //DPRINT(2,"td...");
72+ freetoc(&d->toc);
73+ d->toc = nt;
74+ drawtoc(w, d, &d->toc);
75+ tdb = nt;
76+ alts[DBREQ].op = CHANSND;
77+ break;
78+ case DBREQ: /* sent */
79+ //DPRINT(2,"dreq...");
80+ alts[DBREQ].op = CHANNOP;
81+ break;
82+ case DBREPLY:
83+ //DPRINT(2,"drep...");
84+ freetoc(&d->toc);
85+ d->toc = nt;
86+ redrawtoc(w, &d->toc);
87+ break;
88+ }
89+ }
90+}
91+
92+void
93+threadmain(int argc, char **argv)
94+{
95+ Scsi *s;
96+ Drive *d;
97+ char buf[80];
98+
99+ ARGBEGIN{
100+ case 'v':
101+ debug++;
102+ scsiverbose++;
103+ }ARGEND
104+
105+ if(argc != 1)
106+ usage();
107+
108+ fmtinstall('M', msfconv);
109+
110+ if((s = openscsi(argv[0])) == nil)
111+ error("opening scsi: %r");
112+
113+ d = malloc(sizeof(*d));
114+ if(d == nil)
115+ error("out of memory");
116+ memset(d, 0, sizeof d);
117+
118+ d->scsi = s;
119+ d->w = newwindow();
120+ d->ctocdisp = chancreate(sizeof(Toc), 0);
121+ d->cdbreq = chancreate(sizeof(Toc), 0);
122+ d->cdbreply = chancreate(sizeof(Toc), 0);
123+ d->cstatus = chancreate(sizeof(Cdstatus), 0);
124+
125+ proccreate(wineventproc, d->w, STACK);
126+ proccreate(cddbproc, d, STACK);
127+ proccreate(cdstatusproc, d, STACK);
128+
129+ cleanname(argv[0]);
130+ snprint(buf, sizeof(buf), "%s/", argv[0]);
131+ winname(d->w, buf);
132+
133+ wintagwrite(d->w, "Stop Pause Resume Eject Ingest ", 5+6+7+6+7);
134+ eventwatcher(d);
135+}
acme/bin/source/acd/mkfile+22−0
@@ -0,0 +1,22 @@
1+</$objtype/mkfile
2+
3+TARG=acd
4+BIN=/acme/bin/$objtype
5+
6+OFILES=\
7+ acme.$O\
8+ cddb.$O\
9+ main.$O\
10+ mmc.$O\
11+ util.$O\
12+ win.$O\
13+
14+HFILES=acd.h
15+
16+UPDATE=\
17+ mkfile\
18+ $HFILES\
19+ ${OFILES:%.$O=%.c}\
20+ ${TARG:%=/acme/bin/386/%}\
21+
22+</sys/src/cmd/mkone
acme/bin/source/acd/mmc.c+303−0
@@ -0,0 +1,303 @@
1+#include "acd.h"
2+
3+int
4+msfconv(Fmt *fp)
5+{
6+ Msf m;
7+
8+ m = va_arg(fp->args, Msf);
9+ fmtprint(fp, "%d.%d.%d", m.m, m.s, m.f);
10+ return 0;
11+}
12+
13+static int
14+status(Drive *d)
15+{
16+ uchar cmd[12];
17+
18+ memset(cmd, 0, sizeof cmd);
19+ cmd[0] = 0xBD;
20+ return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
21+}
22+
23+static int
24+playmsf(Drive *d, Msf start, Msf end)
25+{
26+ uchar cmd[12];
27+
28+ memset(cmd, 0, sizeof cmd);
29+ cmd[0] = 0x47;
30+ cmd[3] = start.m;
31+ cmd[4] = start.s;
32+ cmd[5] = start.f;
33+ cmd[6] = end.m;
34+ cmd[7] = end.s;
35+ cmd[8] = end.f;
36+
37+ return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
38+}
39+
40+int
41+playtrack(Drive *d, int start, int end)
42+{
43+ Toc *t;
44+
45+ t = &d->toc;
46+
47+ if(t->ntrack == 0)
48+ return -1;
49+
50+ if(start < 0)
51+ start = 0;
52+ if(end >= t->ntrack)
53+ end = t->ntrack-1;
54+ if(end < start)
55+ end = start;
56+
57+ return playmsf(d, t->track[start].start, t->track[end].end);
58+}
59+
60+int
61+resume(Drive *d)
62+{
63+ uchar cmd[12];
64+
65+ memset(cmd, 0, sizeof cmd);
66+ cmd[0] = 0x4B;
67+ cmd[8] = 0x01;
68+ return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
69+}
70+
71+int
72+pause(Drive *d)
73+{
74+ uchar cmd[12];
75+
76+ memset(cmd, 0, sizeof cmd);
77+ cmd[0] = 0x4B;
78+ return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
79+}
80+
81+int
82+stop(Drive *d)
83+{
84+ uchar cmd[12];
85+
86+ memset(cmd, 0, sizeof cmd);
87+ cmd[0] = 0x4E;
88+ return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
89+}
90+
91+int
92+eject(Drive *d)
93+{
94+ uchar cmd[12];
95+
96+ memset(cmd, 0, sizeof cmd);
97+ cmd[0] = 0x1B;
98+ cmd[1] = 1;
99+ cmd[4] = 2;
100+ return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
101+}
102+
103+int
104+ingest(Drive *d)
105+{
106+ uchar cmd[12];
107+
108+ memset(cmd, 0, sizeof cmd);
109+ cmd[0] = 0x1B;
110+ cmd[1] = 1;
111+ cmd[4] = 3;
112+ return scsi(d->scsi, cmd, sizeof cmd, nil, 0, Snone);
113+}
114+
115+static Msf
116+rdmsf(uchar *p)
117+{
118+ Msf msf;
119+
120+ msf.m = p[0];
121+ msf.s = p[1];
122+ msf.f = p[2];
123+ return msf;
124+}
125+
126+static ulong
127+rdlba(uchar *p)
128+{
129+ return (p[0]<<16) | (p[1]<<8) | p[2];
130+}
131+
132+/* not a Drive, so that we don't accidentally touch Drive.toc */
133+int
134+gettoc(Scsi *s, Toc *t)
135+{
136+ int i, n;
137+ uchar cmd[12];
138+ uchar resp[1024];
139+
140+Again:
141+ memset(t, 0, sizeof(*t));
142+ memset(cmd, 0, sizeof cmd);
143+ cmd[0] = 0x43;
144+ cmd[1] = 0x02;
145+ cmd[7] = sizeof(resp)>>8;
146+ cmd[8] = sizeof(resp);
147+
148+ s->changetime = 1;
149+ /* scsi sets nchange, changetime */
150+ if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
151+ return -1;
152+
153+ if(s->changetime == 0) {
154+ t->ntrack = 0;
155+ werrstr("no media");
156+ return -1;
157+ }
158+
159+ if(t->nchange == s->nchange && t->changetime != 0)
160+ return 0;
161+
162+ t->nchange = s->nchange;
163+ t->changetime = s->changetime;
164+
165+ if(t->ntrack > MTRACK)
166+ t->ntrack = MTRACK;
167+
168+DPRINT(2, "%d %d\n", resp[3], resp[2]);
169+ t->ntrack = resp[3]-resp[2]+1;
170+ t->track0 = resp[2];
171+
172+ n = ((resp[0]<<8) | resp[1])+2;
173+ if(n < 4+8*(t->ntrack+1)) {
174+ werrstr("bad read0 %d %d", n, 4+8*(t->ntrack+1));
175+ return -1;
176+ }
177+
178+ for(i=0; i<=t->ntrack; i++) /* <=: track[ntrack] = end */
179+ t->track[i].start = rdmsf(resp+4+i*8+5);
180+
181+ for(i=0; i<t->ntrack; i++)
182+ t->track[i].end = t->track[i+1].start;
183+
184+ memset(cmd, 0, sizeof cmd);
185+ cmd[0] = 0x43;
186+ cmd[7] = sizeof(resp)>>8;
187+ cmd[8] = sizeof(resp);
188+ if(scsi(s, cmd, sizeof cmd, resp, sizeof(resp), Sread) < 4)
189+ return -1;
190+
191+ if(s->changetime != t->changetime || s->nchange != t->nchange) {
192+ fprint(2, "disk changed underfoot; repeating\n");
193+ goto Again;
194+ }
195+
196+ n = ((resp[0]<<8) | resp[1])+2;
197+ if(n < 4+8*(t->ntrack+1)) {
198+ werrstr("bad read");
199+ return -1;
200+ }
201+
202+ for(i=0; i<=t->ntrack; i++)
203+ t->track[i].bstart = rdlba(resp+4+i*8+5);
204+
205+ for(i=0; i<t->ntrack; i++)
206+ t->track[i].bend = t->track[i+1].bstart;
207+
208+ return 0;
209+}
210+
211+static void
212+dumptoc(Toc *t)
213+{
214+ int i;
215+
216+ fprint(1, "%d tracks\n", t->ntrack);
217+ for(i=0; i<t->ntrack; i++)
218+ print("%d. %M-%M (%lud-%lud)\n", i+1,
219+ t->track[i].start, t->track[i].end,
220+ t->track[i].bstart, t->track[i].bend);
221+}
222+
223+static void
224+ping(Drive *d)
225+{
226+ uchar cmd[12];
227+
228+ memset(cmd, 0, sizeof cmd);
229+ cmd[0] = 0x43;
230+ scsi(d->scsi, cmd, sizeof(cmd), nil, 0, Snone);
231+}
232+
233+static int
234+playstatus(Drive *d, Cdstatus *stat)
235+{
236+ uchar cmd[12], resp[16];
237+
238+ memset(cmd, 0, sizeof cmd);
239+ cmd[0] = 0x42;
240+ cmd[1] = 0x02;
241+ cmd[2] = 0x40;
242+ cmd[3] = 0x01;
243+ cmd[7] = sizeof(resp)>>8;
244+ cmd[8] = sizeof(resp);
245+ if(scsi(d->scsi, cmd, sizeof(cmd), resp, sizeof(resp), Sread) < 0)
246+ return -1;
247+
248+ switch(resp[1]){
249+ case 0x11:
250+ stat->state = Splaying;
251+ break;
252+ case 0x12:
253+ stat->state = Spaused;
254+ break;
255+ case 0x13:
256+ stat->state = Scompleted;
257+ break;
258+ case 0x14:
259+ stat->state = Serror;
260+ break;
261+ case 0x00: /* not supported */
262+ case 0x15: /* no current status to return */
263+ default:
264+ stat->state = Sunknown;
265+ break;
266+ }
267+
268+ stat->track = resp[6];
269+ stat->index = resp[7];
270+ stat->abs = rdmsf(resp+9);
271+ stat->rel = rdmsf(resp+13);
272+ return 0;
273+}
274+
275+void
276+cdstatusproc(void *v)
277+{
278+ Drive *d;
279+ Toc t;
280+ Cdstatus s;
281+
282+ t.changetime = ~0;
283+ t.nchange = ~0;
284+
285+ threadsetname("cdstatusproc");
286+ d = v;
287+ DPRINT(2, "cdstatus %d\n", getpid());
288+ for(;;) {
289+ ping(d);
290+ //DPRINT(2, "d %d %d t %d %d\n", d->scsi->changetime, d->scsi->nchange, t.changetime, t.nchange);
291+ if(playstatus(d, &s) == 0)
292+ send(d->cstatus, &s);
293+ if(d->scsi->changetime != t.changetime || d->scsi->nchange != t.nchange) {
294+ if(gettoc(d->scsi, &t) == 0) {
295+ DPRINT(2, "sendtoc...\n");
296+ if(debug) dumptoc(&t);
297+ send(d->ctocdisp, &t);
298+ } else
299+ DPRINT(2, "error: %r\n");
300+ }
301+ sleep(1000);
302+ }
303+}
acme/bin/source/acd/outline+32−0
@@ -0,0 +1,32 @@
1+acd is composed of four procs
2+
3+wineventproc (win.c:/^wineventproc)
4+ reads acme window events, sends them along w->cevent.
5+
6+cdstatusproc (mmc.c:/^cdstatusproc)
7+ reads cd status once per second, sending
8+ status updates to d->cstatus.
9+ detects disk changes, sends new tocs to d->ctocdisp.
10+
11+cddbproc (cddb.c:/^cddbproc)
12+ reads tocs from d->cdbreq, if it finds
13+ translations in the cddb, sends new tocs to d->cdbreply.
14+
15+eventwatcher (main.c:/^eventwatcher)
16+ the main event loop.
17+ reads status from d->cstatus.
18+ reads events from w->cevent.
19+ reads new tocs to display from d->ctocdisp.
20+ sends new tocs to translate to d->cdbreq.
21+ reads new translated tocs from d->cdbreply.
22+
23+an interesting bug in the original design:
24+ both cdstatusproc and the eventwatcher proc
25+ issue scsi commands. (the eventwatcher responds to
26+ things such as Play, Stop, etc., as well as advancing the track.)
27+
28+ the sd(3) driver did not expect overlapped commands,
29+ and crashed.
30+
31+ this has been fixed by making the scsi(2) commands threadsafe,
32+ and making the sd(3) driver more robust.
acme/bin/source/acd/submit+220−0
@@ -0,0 +1,220 @@
1+CDDB SUBMISSION
2+---------------
3+
4+Your software may allow users to enter CDDB data and then submit them
5+to the freedb archive.
6+There are two methods of submission: <a href="#email">via e-mail</a> or <a href="#http">via http</a> using submit.cgi
7+
8+<a name="email"></a>1. Submission via e-mail
9+------------------------
10+
11+Your software has to send the entry to the
12+following address:
13+
14+ freedb-submit@freedb.org
15+
16+You may implement a button or somesuch in your software's user-interface
17+to facilitate this. The destination e-mail address should be made
18+user-configurable.
19+
20+There should be one e-mail message per freedb entry. The mail Subject
21+line should be in the form "cddb category discid". For example:
22+
23+Subject: cddb rock 850f970b
24+
25+The body of the e-mail message should be in the format of a CDDB file
26+entry as described <a href="http://freedb.freedb.org/software/old/DBFORMAT">here</a>. The messages should contain only
27+plain ASCII text. Do not attach encoded information or add special
28+escape sequences.
29+
30+Note that the disc ID specified in the mail Subject line should
31+also appear in the list of disc IDs in the DISCID= field of the
32+CDDB file entry. If not, it is considered an error and the submission
33+will be rejected.
34+
35+You should only allow categories that are currently supported by the
36+freedb (blues, classical, country, data, folk, jazz, misc, newage,
37+reggae, rock, soundtrack). Submissions specifying unsupported
38+categories will be rejected.
39+
40+Please do not allow a user to submit CD database entries that
41+have completely unfilled contents (i.e., blank information in the
42+disc artist/title as well as the track titles, or filled with
43+useless default information like "track 1", "track 2", etc.).
44+While the current CD database server checks and rejects submissions
45+that have a blank DTITLE line, it doesn't (and can't feasibly) check
46+the track titles effectively, nor can it check any of these fields
47+if they are filled with a default string. If it were, it would
48+have to be hacked to know about the default strings of every possible
49+client.
50+
51+Thus, please design your client with this in mind. This is a somewhat
52+tricky thing to do, as some CDs contain blank tracks with no titles
53+and you need to allow for that. An example minimum requirement
54+that a CD player client should meet is listed below:
55+
56+1. Don't allow the "send" or "submit" feature to be activated if
57+ the CD database information form is not edited at all.
58+2. Check that the disc artist/title contains something (that the user
59+ typed in).
60+3. Check that all of the tracks have a title filled in by the user
61+ (some (but not all!) may be blank, but not the default string).
62+
63+This should minimize the number of useless garbage being submitted
64+into the CD database.
65+
66+Before you release your software, please be sure that it produces
67+submissions that adheres to the CDDB file format, and that the frame
68+offset, disc length, and disc ID information are correctly computed.
69+For testing, please make your software send submissions to the
70+following e-mail address (rather than the real submission site at
71+freedb-submit@freedb.org):
72+
73+ test-submit@freedb.org
74+
75+The test address performs sanity checking on the CDDB submission and
76+sends back pass/fail confirmation, but does not actually deposit the
77+entry in the CD database.
78+
79+<a name="http"></a>2. Submission via http
80+----------------------
81+
82+For submit via http, your application has to transmit the entry to the
83+database through a CGI program at the following URL:
84+
85+http://freedb.freedb.org/~cddb/submit.cgi
86+
87+Submissions are made through the CGI program as follows. You must only use
88+the "POST" method of sending data; "GET" is not supported. There are several
89+HTTP "Entity-Header" fields that must be included in the data followed by a
90+blank line, followed by the "Entity-Body" (a.k.a the CDDB entry) in the
91+format described in Appendix B below. The required header fields are:
92+
93+Category: CDDB_category
94+Discid: CDDB_discid
95+User-Email: user@domain
96+Submit-Mode: test_or_submit
97+Content-Length: length_of_CDDB_entry
98+
99+Where:
100+
101+- "CDDB_category" is one of the valid CDDB categories (blues, classical,
102+ country, data, folk, jazz, misc, newage, reggae, rock, soundtrack).
103+ Invalid categories will result in the entry being rejected.
104+
105+- "CDDB_discid" is the 8-digit hex CDDB disc ID of the entry as described in
106+ the "<a href="http://freedb.freedb.org/sections.php?op=viewarticle&artid=6">Discid howto</a>" section. This must be the same disc ID that appears
107+ in the "DISCID=" section of the entry being submitted. If not, the entry
108+ will be rejected.
109+
110+- "user@domain" is the valid email address of the user submitting the entry.
111+ This is required in case a submission failure notice must be sent to the
112+ user.
113+
114+- "test_or_submit" is the word "test" or "submit" (without the surrounding
115+ quotes) to indicate whether the submission is a test submission or a real
116+ submission to the database, respectively. See <a href="#testsubmission">below</a> for an explanation of
117+ test submissions.
118+
119+- "length_of_CDDB_entry" is the size in bytes of the CDDB entry being
120+ submitted. This number does not include the length of the header or the
121+ blank line separating the HTTP header and the CDDB entry.
122+
123+There are several additional optional HTTP header fields that may also
124+be specified (but which are currently not used by the freedb):
125+
126+Charset: character_set_of_CDDB_entry
127+X-Cddbd-Note: message for user
128+
129+Where:
130+
131+- "character_set_of_CDDB_entry" is one of ISO-8859-1 or US-ASCII (lower case
132+ may be used if desired). This specifies to the CDDB server which character
133+ set the CDDB entry has been encoded in. If your application knows the
134+ user's character set, then you should specify it here. Only these two
135+ character sets are supported currently. DO NOT specify the character set
136+ if your application does not have any way of verifying the user's character
137+ set (i.e. do not guess; it's better not to specify it at all).
138+
139+- "message for user" is an arbitrary message to be included at the top of
140+ any rejection notice that may be sent to the submitting user.
141+
142+An example submission showing the HTTP command, "Entity-Header" and "Entity-
143+Body" follows:
144+
145+POST /~cddb/submit.cgi HTTP/1.0
146+Category: rock
147+Discid: 2a09310a
148+User-Email: joe@joeshost.joesdomain.com
149+Submit-Mode: submit
150+Charset: ISO-8859-1
151+X-Cddbd-Note: Problems with Super CD Player? Send email to support@supercd.com.
152+Content-Length: 820
153+
154+# xmcd
155+#
156+# Track frame offsets:
157+[ data omitted in this example for brevity ]
158+PLAYORDER=
159+
160+Note the blank line between the "Content-Length" header field and the
161+"# xmcd" which marks the beginning of the CDDB entry.
162+
163+When your application submits an entry through the CGI program, it will
164+respond with a 3-digit response code indicating whether or not the entry has
165+been forwarded to the freedb server for inclusion in the database, followed
166+by a textual description of the response code. For example:
167+
168+200 OK, submission has been sent.
169+400 Internal error: failed to forward submission.
170+500 Missing required header information.
171+
172+These are but a few of the possible responses.
173+See the description of the <a href="http://freedb.freedb.org/sections.php?op=viewarticle&artid=28">CDDB server protocol</a> for more information on
174+handling response codes.
175+
176+The body of the freedb entry being submitted should be sent verbatim as
177+described in the <a href="http://freedb.freedb.org/software/old/DBFORMAT">database-format specification</a>. DO NOT encode the data in any
178+way before transmitting it; data must be sent as raw text. For example,
179+Windows programmers should not use the Windows URL encode function prior to
180+calling the submit CGI program. Doing so may lead to corrupt data being sent
181+and also possibly to rejected submissions.
182+
183+You may implement a button or somesuch in your software's user interface
184+to initiate submissions. Rejected submissions are automatically returned
185+via email to the sender specified in the "User-Email" header field with an
186+explanation of the reason for the rejection.
187+
188+Please do not allow a user to submit CD database entries that
189+have completely unfilled contents (i.e., blank information in the
190+disc artist/title as well as the track titles, or filled with
191+useless default information like "track 1", "track 2", etc.).
192+While the current CD database server checks and rejects submissions
193+that have a blank DTITLE line, it doesn't (and can't feasibly) check
194+the track titles effectively, nor can it check any of these fields
195+if they are filled with a default string. If it were, it would
196+have to be hacked to know about the default strings of every possible
197+client.
198+
199+Thus, please design your client with this in mind. This is a somewhat
200+tricky thing to do, as some CDs contain blank tracks with no titles
201+and you need to allow for that. An example minimum requirement
202+that a CD player client should meet is listed below:
203+
204+1. Don't allow the "send" or "submit" feature to be activated if
205+ the CD database information form is not edited at all.
206+2. Check that the disc artist/title contains something (that the user
207+ typed in).
208+3. Check that all of the tracks have a title filled in by the user.
209+ (some (but not all!) may be blank, but not the default string).
210+
211+Before you release your software, please be sure that it produces
212+submissions that adhere to the CDDB file format, and that the frame
213+offset, disc length, and disc ID information are correctly computed.
214+For testing, please make your software send submissions with the
215+"Submit-Mode" HTTP header field set to "test".
216+
217+<a name="testsubmission"></a>CDDB submissions sent in test mode will be sanity-checked by the freedb server
218+and pass/fail confirmation sent back to the submitter, but will not actually
219+be deposited in the CD database. Please DO NOT send submisions in "submit"
220+mode until you have tested your program with several different CD's.
acme/bin/source/acd/toc.c+59−0
@@ -0,0 +1,59 @@
1+#include "acd.h"
2+
3+Toc thetoc;
4+
5+void
6+tocthread(void *v)
7+{
8+ Drive *d;
9+
10+ threadsetname("tocthread");
11+ d = v;
12+ DPRINT(2, "recv ctocdisp?...");
13+ while(recv(d->ctocdisp, &thetoc) == 1) {
14+ DPRINT(2, "recv ctocdisp!...");
15+ drawtoc(d->w, &thetoc);
16+ DPRINT(2, "send dbreq...\n");
17+ send(d->ctocdbreq, &thetoc);
18+ }
19+}
20+
21+void
22+freetoc(Toc *t)
23+{
24+ int i;
25+
26+ free(t->title);
27+ for(i=0; i<t->ntrack; i++)
28+ free(t->track[i].title);
29+}
30+
31+void
32+cddbthread(void *v)
33+{
34+ Drive *d;
35+ Toc t;
36+
37+ threadsetname("cddbthread");
38+ d = v;
39+ while(recv(d->ctocdbreply, &t) == 1) {
40+ if(thetoc.nchange == t.nchange) {
41+ freetoc(&thetoc);
42+ thetoc = t;
43+ redrawtoc(d->w, &thetoc);
44+ }
45+ }
46+}
47+
48+void
49+cdstatusthread(void *v)
50+{
51+ Drive *d;
52+ Cdstatus s;
53+
54+ d = v;
55+
56+ for(;;)
57+ recv(d->cstat, &s);
58+
59+}
acme/bin/source/acd/util.c+89−0
@@ -0,0 +1,89 @@
1+#include "acd.h"
2+
3+void*
4+emalloc(uint n)
5+{
6+ void *p;
7+
8+ p = malloc(n);
9+ if(p == nil)
10+ error("can't malloc: %r");
11+ memset(p, 0, n);
12+ return p;
13+}
14+
15+char*
16+estrdup(char *s)
17+{
18+ char *t;
19+
20+ t = emalloc(strlen(s)+1);
21+ strcpy(t, s);
22+ return t;
23+}
24+
25+char*
26+estrstrdup(char *s, char *t)
27+{
28+ char *u;
29+
30+ u = emalloc(strlen(s)+strlen(t)+1);
31+ strcpy(u, s);
32+ strcat(u, t);
33+ return u;
34+}
35+
36+char*
37+eappend(char *s, char *sep, char *t)
38+{
39+ char *u;
40+
41+ if(t == nil)
42+ u = estrstrdup(s, sep);
43+ else{
44+ u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1);
45+ strcpy(u, s);
46+ strcat(u, sep);
47+ strcat(u, t);
48+ }
49+ free(s);
50+ return u;
51+}
52+
53+char*
54+egrow(char *s, char *sep, char *t)
55+{
56+ s = eappend(s, sep, t);
57+ free(t);
58+ return s;
59+}
60+
61+void
62+error(char *fmt, ...)
63+{
64+ int n;
65+ va_list arg;
66+ char buf[256];
67+
68+ fprint(2, "Mail: ");
69+ va_start(arg, fmt);
70+ n = vsnprint(buf, sizeof buf, fmt, arg);
71+ va_end(arg);
72+ write(2, buf, n);
73+ write(2, "\n", 1);
74+ threadexitsall(fmt);
75+}
76+
77+void
78+ctlprint(int fd, char *fmt, ...)
79+{
80+ int n;
81+ va_list arg;
82+ char buf[256];
83+
84+ va_start(arg, fmt);
85+ n = vsnprint(buf, sizeof buf, fmt, arg);
86+ va_end(arg);
87+ if(write(fd, buf, n) != n)
88+ error("control file write error: %r");
89+}
acme/bin/source/acd/win.c+320−0
@@ -0,0 +1,320 @@
1+#include "acd.h"
2+
3+Window*
4+newwindow(void)
5+{
6+ char buf[12];
7+ Window *w;
8+
9+ w = emalloc(sizeof(Window));
10+ w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC);
11+ if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
12+ error("can't open window ctl file: %r");
13+ ctlprint(w->ctl, "noscroll\n");
14+ w->id = atoi(buf);
15+ w->event = winopenfile(w, "event");
16+ w->addr = -1; /* will be opened when needed */
17+ w->body = nil;
18+ w->data = -1;
19+ w->cevent = chancreate(sizeof(Event*), 0);
20+ if(w->cevent == nil)
21+ error("cevent is nil: %r");
22+ return w;
23+}
24+
25+void
26+winsetdump(Window *w, char *dir, char *cmd)
27+{
28+ if(dir != nil)
29+ ctlprint(w->ctl, "dumpdir %s\n", dir);
30+ if(cmd != nil)
31+ ctlprint(w->ctl, "dump %s\n", cmd);
32+}
33+
34+void
35+wineventproc(void *v)
36+{
37+ Window *w;
38+ int i;
39+
40+ threadsetname("wineventproc");
41+ w = v;
42+ for(i=0; ; i++){
43+ if(i >= NEVENT)
44+ i = 0;
45+ wingetevent(w, &w->e[i]);
46+ sendp(w->cevent, &w->e[i]);
47+ }
48+}
49+
50+int
51+winopenfile(Window *w, char *f)
52+{
53+ char buf[64];
54+ int fd;
55+
56+ sprint(buf, "/mnt/wsys/%d/%s", w->id, f);
57+ fd = open(buf, ORDWR|OCEXEC);
58+ if(fd < 0)
59+ error("can't open window file %s: %r", f);
60+ return fd;
61+}
62+
63+void
64+wintagwrite(Window *w, char *s, int n)
65+{
66+ int fd;
67+
68+ fd = winopenfile(w, "tag");
69+ if(write(fd, s, n) != n)
70+ error("tag write: %r");
71+ close(fd);
72+}
73+
74+void
75+winname(Window *w, char *s)
76+{
77+ ctlprint(w->ctl, "name %s\n", s);
78+}
79+
80+void
81+winopenbody(Window *w, int mode)
82+{
83+ char buf[256];
84+
85+ sprint(buf, "/mnt/wsys/%d/body", w->id);
86+ w->body = Bopen(buf, mode|OCEXEC);
87+ if(w->body == nil)
88+ error("can't open window body file: %r");
89+}
90+
91+void
92+winclosebody(Window *w)
93+{
94+ if(w->body != nil){
95+ Bterm(w->body);
96+ w->body = nil;
97+ }
98+}
99+
100+void
101+winwritebody(Window *w, char *s, int n)
102+{
103+ if(w->body == nil)
104+ winopenbody(w, OWRITE);
105+ if(Bwrite(w->body, s, n) != n)
106+ error("write error to window: %r");
107+}
108+
109+int
110+wingetec(Window *w)
111+{
112+ if(w->nbuf == 0){
113+ w->nbuf = read(w->event, w->buf, sizeof w->buf);
114+ if(w->nbuf <= 0){
115+ /* probably because window has exited, and only called by wineventproc, so just shut down */
116+ threadexits(nil);
117+ }
118+ w->bufp = w->buf;
119+ }
120+ w->nbuf--;
121+ return *w->bufp++;
122+}
123+
124+int
125+wingeten(Window *w)
126+{
127+ int n, c;
128+
129+ n = 0;
130+ while('0'<=(c=wingetec(w)) && c<='9')
131+ n = n*10+(c-'0');
132+ if(c != ' ')
133+ error("event number syntax");
134+ return n;
135+}
136+
137+int
138+wingeter(Window *w, char *buf, int *nb)
139+{
140+ Rune r;
141+ int n;
142+
143+ r = wingetec(w);
144+ buf[0] = r;
145+ n = 1;
146+ if(r >= Runeself) {
147+ while(!fullrune(buf, n))
148+ buf[n++] = wingetec(w);
149+ chartorune(&r, buf);
150+ }
151+ *nb = n;
152+ return r;
153+}
154+
155+void
156+wingetevent(Window *w, Event *e)
157+{
158+ int i, nb;
159+
160+ e->c1 = wingetec(w);
161+ e->c2 = wingetec(w);
162+ e->q0 = wingeten(w);
163+ e->q1 = wingeten(w);
164+ e->flag = wingeten(w);
165+ e->nr = wingeten(w);
166+ if(e->nr > EVENTSIZE)
167+ error("event string too long");
168+ e->nb = 0;
169+ for(i=0; i<e->nr; i++){
170+ e->r[i] = wingeter(w, e->b+e->nb, &nb);
171+ e->nb += nb;
172+ }
173+ e->r[e->nr] = 0;
174+ e->b[e->nb] = 0;
175+ if(wingetec(w) != '\n')
176+ error("event syntax error");
177+}
178+
179+void
180+winwriteevent(Window *w, Event *e)
181+{
182+ fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
183+}
184+
185+static int
186+nrunes(char *s, int nb)
187+{
188+ int i, n;
189+ Rune r;
190+
191+ n = 0;
192+ for(i=0; i<nb; n++)
193+ i += chartorune(&r, s+i);
194+ return n;
195+}
196+
197+void
198+winread(Window *w, uint q0, uint q1, char *data)
199+{
200+ int m, n, nr;
201+ char buf[256];
202+
203+ if(w->addr < 0)
204+ w->addr = winopenfile(w, "addr");
205+ if(w->data < 0)
206+ w->data = winopenfile(w, "data");
207+ m = q0;
208+ while(m < q1){
209+ n = sprint(buf, "#%d", m);
210+ if(write(w->addr, buf, n) != n)
211+ error("error writing addr: %r");
212+ n = read(w->data, buf, sizeof buf);
213+ if(n <= 0)
214+ error("reading data: %r");
215+ nr = nrunes(buf, n);
216+ while(m+nr >q1){
217+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
218+ --nr;
219+ }
220+ if(n == 0)
221+ break;
222+ memmove(data, buf, n);
223+ data += n;
224+ *data = 0;
225+ m += nr;
226+ }
227+}
228+
229+void
230+windormant(Window *w)
231+{
232+ if(w->addr >= 0){
233+ close(w->addr);
234+ w->addr = -1;
235+ }
236+ if(w->body != nil){
237+ Bterm(w->body);
238+ w->body = nil;
239+ }
240+ if(w->data >= 0){
241+ close(w->data);
242+ w->data = -1;
243+ }
244+}
245+
246+
247+int
248+windel(Window *w, int sure)
249+{
250+ if(sure)
251+ write(w->ctl, "delete\n", 7);
252+ else if(write(w->ctl, "del\n", 4) != 4)
253+ return 0;
254+ /* event proc will die due to read error from event file */
255+ windormant(w);
256+ close(w->ctl);
257+ w->ctl = -1;
258+ close(w->event);
259+ w->event = -1;
260+ return 1;
261+}
262+
263+void
264+winclean(Window *w)
265+{
266+ if(w->body)
267+ Bflush(w->body);
268+ ctlprint(w->ctl, "clean\n");
269+}
270+
271+int
272+winsetaddr(Window *w, char *addr, int errok)
273+{
274+ if(w->addr < 0)
275+ w->addr = winopenfile(w, "addr");
276+ if(write(w->addr, addr, strlen(addr)) < 0){
277+ if(!errok)
278+ error("error writing addr(%s): %r", addr);
279+ return 0;
280+ }
281+ return 1;
282+}
283+
284+int
285+winselect(Window *w, char *addr, int errok)
286+{
287+ if(winsetaddr(w, addr, errok)){
288+ ctlprint(w->ctl, "dot=addr\n");
289+ return 1;
290+ }
291+ return 0;
292+}
293+
294+char*
295+winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */
296+{
297+ char *s;
298+ int m, na, n;
299+
300+ if(w->body != nil)
301+ winclosebody(w);
302+ winopenbody(w, OREAD);
303+ s = nil;
304+ na = 0;
305+ n = 0;
306+ for(;;){
307+ if(na < n+512){
308+ na += 1024;
309+ s = realloc(s, na+1);
310+ }
311+ m = Bread(w->body, s+n, na-n);
312+ if(m <= 0)
313+ break;
314+ n += m;
315+ }
316+ s[n] = 0;
317+ winclosebody(w);
318+ *np = n;
319+ return s;
320+}
acme/bin/source/adict/_adict.c+584−0
@@ -0,0 +1,584 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include "win.h"
6+#include "adict.h"
7+
8+char *prog = "adict";
9+char *lprog = "/bin/adict";
10+char *xprog = "/bin/dict";
11+char *dict, *pattern, *curaddr[MAXMATCH], *curone, *args[6], buffer[80];
12+char abuffer[80], fbuffer[80], pbuffer[80];
13+int curindex, count, Eopen, Mopen;
14+Win Mwin, Ewin, Dwin;
15+
16+void openwin(char*, char*, Win*, int);
17+void handle(Win*, int);
18+void rexec(void*);
19+void pexec(void*);
20+int getaddr(char*);
21+
22+void
23+usage(void)
24+{
25+ threadprint(2, "usage: %s [-d dictname] [pattern]\n", argv0);
26+ threadexitsall(nil);
27+}
28+
29+void
30+threadmain(int argc, char** argv)
31+{
32+ ARGBEGIN{
33+ case 'd':
34+ dict = strdup(ARGF());
35+ break;
36+ default:
37+ usage();
38+ }ARGEND
39+
40+ /* if running as other name, note that fact */
41+ if(access(argv0, AEXIST) == 0)
42+ lprog = argv0;
43+
44+ switch(argc){
45+ case 1:
46+ pattern = pbuffer;
47+ strcpy(pattern,argv[0]);
48+ if(dict == nil)
49+ dict = "oed";
50+ break;
51+ case 0:
52+ break;
53+ default:
54+ usage();
55+ }
56+
57+ if ((dict == nil) && (pattern == nil))
58+ openwin(prog,"", &Dwin, Dictwin);
59+ if (pattern == nil)
60+ openwin(prog,"",&Ewin, Entrywin);
61+ if ((count = getaddr(pattern)) <= 1)
62+ openwin(prog,"Prev Next", &Ewin, Entrywin);
63+ else
64+ openwin(prog, "", &Mwin, Matchwin);
65+}
66+
67+static int
68+procrexec(char *xprog, ...)
69+{
70+ int fpipe[2];
71+ void *rexarg[4];
72+ Channel *c;
73+ va_list va;
74+ int i;
75+ char *p;
76+
77+ pipe(fpipe);
78+ va_start(va, xprog);
79+ p = xprog;
80+ for(i=0; p && i+1<nelem(args); i++){
81+ args[i] = p;
82+ p = va_arg(va, char*);
83+ }
84+ args[i] = nil;
85+
86+ c = chancreate(sizeof(ulong), 0);
87+ rexarg[0] = xprog;
88+ rexarg[1] = args;
89+ rexarg[2] = fpipe;
90+ rexarg[3] = c;
91+
92+ proccreate(rexec, rexarg, 8192);
93+ recvul(c);
94+ chanfree(c);
95+ close(fpipe[1]);
96+ return fpipe[0];
97+}
98+
99+int
100+getaddr(char *pattern)
101+{
102+ /* Get char offset into dictionary of matches. */
103+
104+ int fd, i;
105+ Biobuf inbuf;
106+ char *bufptr;
107+char *obuf;
108+
109+ if (pattern == nil) {
110+ curone = nil;
111+ curindex = 0;
112+ curaddr[curindex] = nil;
113+ return 0;
114+ }
115+
116+ sprint(buffer,"/%s/A", pattern);
117+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
118+ Binit(&inbuf, fd, OREAD);
119+ i = 0;
120+ curindex = 0;
121+ while ((bufptr = Brdline(&inbuf, '\n')) != nil && (i < (MAXMATCH-1))) {
122+ bufptr[Blinelen(&inbuf)-1] = 0;
123+obuf=bufptr;
124+ while (bufptr[0] != '#' && bufptr[0] != 0) bufptr++;
125+if(bufptr[0] == 0)
126+ print("whoops buf «%s»\n", obuf);
127+ curaddr[i] = malloc(strlen(bufptr));
128+ strcpy(curaddr[i], bufptr);
129+ i++;
130+ }
131+ curaddr[i] = nil;
132+ if (i == MAXMATCH)
133+ threadprint(2, "Too many matches!\n");
134+ Bterm(&inbuf);
135+ close(fd);
136+
137+ curone = curaddr[curindex];
138+ return(i);
139+}
140+
141+char*
142+getpattern(char *addr)
143+{
144+ /* Get the pattern corresponding to an absolute address.*/
145+ int fd;
146+ char *res, *t;
147+
148+ res = nil;
149+ sprint(buffer,"%sh", addr);
150+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
151+ if (read(fd, pbuffer, 80) > 80)
152+ threadprint(2, "Error in getting addres from dict.\n");
153+ else {
154+ t = pbuffer;
155+ /* remove trailing whitespace, newline */
156+ if (t != nil){
157+ while(*t != 0 && *t != '\n')
158+ t++;
159+ if(t == 0 && t > pbuffer)
160+ t--;
161+ while(t >= pbuffer && (*t==' ' || *t=='\n' || *t=='\t' || *t=='\r'))
162+ *t-- = 0;
163+ }
164+ res = pbuffer;
165+ }
166+ close(fd);
167+ return(res);
168+}
169+
170+char*
171+chgaddr(int dir)
172+{
173+ /* Increment or decrement the current address (curone). */
174+
175+ int fd;
176+ char *res, *t;
177+
178+ res = nil;
179+ if (dir < 0)
180+ sprint(buffer,"%s-a", curone);
181+ else
182+ sprint(buffer,"%s+a", curone);
183+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
184+ if (read(fd, abuffer, 80) > 80)
185+ threadprint(2, "Error in getting addres from dict.\n");
186+ else {
187+ res = abuffer;
188+ while (*res != '#') res++;
189+ t = res;
190+ while ((*t != '\n') && (t != nil)) t++;
191+ if (t != nil) *t = 0;
192+ }
193+ close(fd);
194+ return(res);
195+}
196+
197+void
198+dispdicts(Win *cwin)
199+{
200+ /* Display available dictionaries in window. */
201+
202+ int fd, nb, i;
203+ char buf[1024], *t;
204+
205+ fd = procrexec(xprog, "-d", "?", nil);
206+ wreplace(cwin, "0,$","",0); /* Clear window */
207+ while ((nb = read(fd, buf, 1024)) > 0) {
208+ t = buf;
209+ i = 0;
210+ if (strncmp("Usage", buf, 5) == 0) { /* Remove first line. */
211+ while (t[0] != '\n') {
212+ t++;
213+ i++;
214+ }
215+ t++;
216+ i++;
217+ }
218+ wwritebody(cwin, t, nb-i);
219+ }
220+ close(fd);
221+ wclean(cwin);
222+}
223+
224+void
225+dispentry(Win *cwin)
226+{
227+ /* Display the current selection in window. */
228+
229+ int fd, nb;
230+ char buf[BUFSIZE];
231+
232+ if (curone == nil) {
233+ if (pattern != nil) {
234+ sprint(buf,"Pattern not found.\n");
235+ wwritebody(cwin, buf, 19);
236+ wclean(cwin);
237+ }
238+ return;
239+ }
240+ sprint(buffer,"%sp", curone);
241+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
242+ wreplace(cwin, "0,$","",0); /* Clear window */
243+ while ((nb = read(fd, buf, BUFSIZE)) > 0) {
244+ wwritebody(cwin, buf, nb);
245+ }
246+ close(fd);
247+ wclean(cwin);
248+}
249+
250+void
251+dispmatches(Win *cwin)
252+{
253+ /* Display the current matches. */
254+
255+ int fd, nb;
256+ char buf[BUFSIZE];
257+
258+ sprint(buffer,"/%s/H", pattern);
259+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
260+ while ((nb = read(fd, buf, BUFSIZE)) > 0)
261+ wwritebody(cwin, buf, nb);
262+ close(fd);
263+ wclean(cwin);
264+}
265+
266+char*
267+format(char *s)
268+{
269+ /* Format a string to be written in window tag. Acme doesn't like */
270+ /* non alpha-num's in the tag line. */
271+
272+ char *t, *h;
273+
274+ t = fbuffer;
275+ if (s == nil) {
276+ *t = 0;
277+ return t;
278+ }
279+ strcpy(t, s);
280+ h = t;
281+ while (*t != 0) {
282+ if (!(((*t >= 'a') && (*t <= 'z')) ||
283+ ((*t >= 'A') && (*t <= 'Z')) ||
284+ ((*t >= '0') && (*t <= '9'))))
285+ *t = '_';
286+ t++;
287+ }
288+ if (strlen(h) > MAXTAG)
289+ h[MAXTAG] = 0;
290+ if (strcmp(s,h) == 0) return s;
291+ return h;
292+}
293+
294+void
295+openwin(char *name, char *buttons, Win *twin, int wintype)
296+{
297+ char buf[80];
298+
299+ wnew(twin);
300+ if (wintype == Dictwin)
301+ sprint(buf,"%s",name);
302+ else
303+ if ((wintype == Entrywin) && (count > 1))
304+ sprint(buf,"%s/%s/%s/%d",name, dict, format(pattern), curindex+1);
305+ else
306+ sprint(buf,"%s/%s/%s",name, dict, format(pattern));
307+ wname(twin, buf);
308+ wtagwrite(twin, buttons, strlen(buttons));
309+ wclean(twin);
310+ wdormant(twin);
311+ if (wintype == Dictwin)
312+ dispdicts(twin);
313+ if (wintype == Matchwin) {
314+ Mopen = True;
315+ dispmatches(twin);
316+ }
317+ if (wintype == Entrywin) {
318+ Eopen = True;
319+ dispentry(twin);
320+ }
321+ handle(twin, wintype);
322+}
323+
324+void
325+vopenwin(void *v)
326+{
327+ void **arg;
328+ char *name, *buttons;
329+ Win *twin;
330+ int wintype;
331+
332+ arg = v;
333+ name = arg[0];
334+ buttons = arg[1];
335+ twin = arg[2];
336+ wintype = (int)arg[3];
337+ sendul(arg[4], 0);
338+
339+ openwin(name, buttons, twin, wintype);
340+ threadexits(nil);
341+}
342+
343+void
344+procopenwin(char *name, char *buttons, Win *twin, int wintype)
345+{
346+ void *arg[5];
347+ Channel *c;
348+
349+ c = chancreate(sizeof(ulong), 0);
350+ arg[0] = name;
351+ arg[1] = buttons;
352+ arg[2] = twin;
353+ arg[3] = (void*)wintype;
354+ arg[4] = c;
355+ proccreate(vopenwin, arg, 8192);
356+ recvul(c);
357+ chanfree(c);
358+}
359+
360+void
361+rexec(void *v)
362+{
363+ void **arg;
364+ char *prog;
365+ char **args;
366+ int *fd;
367+ Channel *c;
368+
369+ arg = v;
370+ prog = arg[0];
371+ args = arg[1];
372+ fd = arg[2];
373+ c = arg[3];
374+
375+ rfork(RFENVG|RFFDG);
376+ dup(fd[1], 1);
377+ close(fd[1]);
378+ close(fd[0]);
379+ procexec(c, prog, args);
380+ threadprint(2, "Remote pipe execution failed: %s %r\n", prog);
381+abort();
382+ threadexits(nil);
383+}
384+
385+void
386+pexec(void *v)
387+{
388+ void **arg;
389+ char *prog;
390+ char **args;
391+ Channel *c;
392+
393+ arg = v;
394+ prog = arg[0];
395+ args = arg[1];
396+ c = arg[2];
397+
398+ procexec(c, prog, args);
399+ threadprint(2, "Remote execution failed: %s %r\n", prog);
400+abort();
401+ threadexits(nil);
402+}
403+
404+void
405+procpexec(char *prog, char **args)
406+{
407+ void *rexarg[4];
408+ Channel *c;
409+
410+ c = chancreate(sizeof(ulong), 0);
411+ rexarg[0] = prog;
412+ rexarg[1] = args;
413+ rexarg[2] = c;
414+
415+ proccreate(pexec, rexarg, 8192);
416+ recvul(c);
417+ chanfree(c);
418+}
419+
420+void
421+kill(void)
422+{
423+ /* Kill all processes related to this one. */
424+ int fd;
425+
426+ sprint(buffer, "/proc/%d/notepg", getpid());
427+ fd = open(buffer, OWRITE);
428+ rfork(RFNOTEG);
429+ write(fd, "kill", 4);
430+}
431+
432+int
433+command(char *com, Win *w, int wintype)
434+{
435+ char *buf;
436+
437+ if (strncmp(com, "Del", 3) == 0) {
438+ switch(wintype){
439+ case Entrywin:
440+ if (wdel(w)) {
441+ Eopen = False;
442+ threadexits(nil);
443+ }
444+ break;
445+ case Dictwin:
446+ if (wdel(w))
447+ threadexits(nil);
448+ break;
449+ case Matchwin:
450+ kill();
451+ if (Eopen)
452+ if (~wdel(&Ewin)) /* Remove the entry window */
453+ wdel(&Ewin);
454+ if (!wdel(w))
455+ wdel(w);
456+ threadexits(nil);
457+ break;
458+ }
459+ return True;
460+ }
461+ if (strncmp(com, "Next", 4) == 0){
462+ if (curone != nil) {
463+ curone = chgaddr(1);
464+ buf = getpattern(curone);
465+ sprint(buffer,"%s/%s/%s", prog, dict, format(buf));
466+ wname(w, buffer);
467+ dispentry(w);
468+ }
469+ return True;
470+ }
471+ if (strncmp(com, "Prev",4) == 0){
472+ if (curone != nil) {
473+ curone = chgaddr(-1);
474+ buf = getpattern(curone);
475+ sprint(buffer,"%s/%s/%s", prog, dict, format(buf));
476+ wname(w, buffer);
477+ dispentry(w);
478+ }
479+ return True;
480+ }
481+ if (strncmp(com, "Nmatch",6) == 0){
482+ if (curaddr[++curindex] == nil)
483+ curindex = 0;
484+ curone = curaddr[curindex];
485+ if (curone != nil) {
486+ sprint(buffer,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1);
487+ wname(w, buffer);
488+ dispentry(w);
489+ }
490+ return True;
491+ }
492+ return False;
493+}
494+
495+void
496+handle(Win *w, int wintype)
497+{
498+ Event e, e2, ea, etoss;
499+ char *s, *t, buf[80];
500+ int tmp, na;
501+
502+ while (True) {
503+ wevent(w, &e);
504+ switch(e.c2){
505+ default:
506+ /* threadprint(2,"unknown message %c%c\n", e.c1, e.c2); */
507+ break;
508+ case 'i':
509+ /* threadprint(2,"'%s' inserted in tag at %d\n", e.b, e.q0);*/
510+ break;
511+ case 'I':
512+ /* threadprint(2,"'%s' inserted in body at %d\n", e.b, e.q0);*/
513+ break;
514+ case 'd':
515+ /* threadprint(2, "'%s' deleted in tag at %d\n", e.b, e.q0);*/
516+ break;
517+ case 'D':
518+ /* threadprint(2, "'%s' deleted in body at %d\n", e.b, e.q0);*/
519+ break;
520+ case 'x':
521+ case 'X': /* Execute command. */
522+ if (e.flag & 2)
523+ wevent(w, &e2);
524+ if(e.flag & 8){
525+ wevent(w, &ea);
526+ wevent(w, &etoss);
527+ na = ea.nb;
528+ } else
529+ na = 0;
530+ s = e.b;
531+ if ((e.flag & 2) && e.nb == 0)
532+ s = e2.b;
533+ if(na){
534+ t = malloc(strlen(s)+1+na+1);
535+ snprint(t, strlen(s)+1+na+1, "%s %s", s, ea.b);
536+ s = t;
537+ }
538+ /* if it's a long message, it can't be for us anyway */
539+ if(!command(s, w, wintype)) /* send it back */
540+ wwriteevent(w, &e);
541+ if(na)
542+ free(s);
543+ break;
544+ case 'l':
545+ case 'L': /* Look for something. */
546+ if (e.flag & 2)
547+ wevent(w, &e);
548+ wclean(w); /* Set clean bit. */
549+ if (wintype == Dictwin) {
550+ strcpy(buf, e.b);
551+ args[0] = lprog;
552+ args[1] = "-d";
553+ args[2] = buf;
554+ args[3] = nil;
555+ procpexec(lprog, args); /* New adict with chosen dict. */
556+ }
557+ if (wintype == Entrywin) {
558+ strcpy(buf, e.b);
559+ args[0] = lprog;
560+ args[1] = "-d";
561+ args[2] = dict;
562+ args[3] = buf;
563+ args[4] = nil;
564+ procpexec(lprog, args); /* New adict with chosen pattern. */
565+ }
566+ if (wintype == Matchwin) {
567+ tmp = atoi(e.b) - 1;
568+ if ((tmp >= 0) && (tmp < MAXMATCH) && (curaddr[tmp] != nil)) {
569+ curindex = tmp;
570+ curone = curaddr[curindex];
571+ /* Display selected match. */
572+ if (Eopen) {
573+ sprint(buf,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1);
574+ wname(&Ewin, buf);
575+ dispentry(&Ewin);
576+ }
577+ else
578+ procopenwin(prog,"Nmatch Prev Next", &Ewin, Entrywin);
579+ }
580+ }
581+ break;
582+ }
583+ }
584+}
acme/bin/source/adict/_win.c+315−0
@@ -0,0 +1,315 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include "win.h"
6+
7+void*
8+erealloc(void *p, uint n)
9+{
10+ p = realloc(p, n);
11+ if(p == nil)
12+ threadprint(2, "realloc failed: %r");
13+ return p;
14+}
15+
16+void
17+wnew(Win *w)
18+{
19+ char buf[12];
20+
21+ w->ctl = open("/mnt/acme/new/ctl", ORDWR);
22+ if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
23+ threadprint (2, "can't open window ctl file: %r");
24+ ctlwrite(w, "noscroll\n");
25+ w->winid = atoi(buf);
26+ w->event = openfile(w, "event");
27+ w->addr = -1; /* will be opened when needed */
28+ w->body = nil;
29+ w->data = -1;
30+}
31+
32+int
33+openfile(Win *w, char *f)
34+{
35+ char buf[64];
36+ int fd;
37+
38+ sprint(buf, "/mnt/acme/%d/%s", w->winid, f);
39+ fd = open(buf, ORDWR|OCEXEC);
40+ if(fd < 0)
41+ threadprint (2,"can't open window %s file: %r", f);
42+ return fd;
43+}
44+
45+void
46+openbody(Win *w, int mode)
47+{
48+ char buf[64];
49+
50+ sprint(buf, "/mnt/acme/%d/body", w->winid);
51+ w->body = Bopen(buf, mode|OCEXEC);
52+ if(w->body == nil)
53+ threadprint(2,"can't open window body file: %r");
54+}
55+
56+void
57+wwritebody(Win *w, char *s, int n)
58+{
59+ if(w->body == nil)
60+ openbody(w, OWRITE);
61+ if(Bwrite(w->body, s, n) != n)
62+ threadprint(2,"write error to window: %r");
63+ Bflush(w->body);
64+}
65+
66+void
67+wreplace(Win *w, char *addr, char *repl, int nrepl)
68+{
69+ if(w->addr < 0)
70+ w->addr = openfile(w, "addr");
71+ if(w->data < 0)
72+ w->data = openfile(w, "data");
73+ if(write(w->addr, addr, strlen(addr)) < 0){
74+ threadprint(2, "mail: warning: badd address %s:%r\n", addr);
75+ return;
76+ }
77+ if(write(w->data, repl, nrepl) != nrepl)
78+ threadprint(2, "writing data: %r");
79+}
80+
81+static int
82+nrunes(char *s, int nb)
83+{
84+ int i, n;
85+ Rune r;
86+
87+ n = 0;
88+ for(i=0; i<nb; n++)
89+ i += chartorune(&r, s+i);
90+ return n;
91+}
92+
93+void
94+wread(Win *w, uint q0, uint q1, char *data)
95+{
96+ int m, n, nr;
97+ char buf[256];
98+
99+ if(w->addr < 0)
100+ w->addr = openfile(w, "addr");
101+ if(w->data < 0)
102+ w->data = openfile(w, "data");
103+ m = q0;
104+ while(m < q1){
105+ n = sprint(buf, "#%d", m);
106+ if(write(w->addr, buf, n) != n)
107+ threadprint(2,"writing addr: %r");
108+ n = read(w->data, buf, sizeof buf);
109+ if(n <= 0)
110+ threadprint(2,"reading data: %r");
111+ nr = nrunes(buf, n);
112+ while(m+nr >q1){
113+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
114+ --nr;
115+ }
116+ if(n == 0)
117+ break;
118+ memmove(data, buf, n);
119+ data += n;
120+ *data = 0;
121+ m += nr;
122+ }
123+}
124+
125+void
126+wselect(Win *w, char *addr)
127+{
128+ if(w->addr < 0)
129+ w->addr = openfile(w, "addr");
130+ if(write(w->addr, addr, strlen(addr)) < 0)
131+ threadprint(2,"writing addr");
132+ ctlwrite(w, "dot=addr\n");
133+}
134+
135+void
136+wtagwrite(Win *w, char *s, int n)
137+{
138+ int fd;
139+
140+ fd = openfile(w, "tag");
141+ if(write(fd, s, n) != n)
142+ threadprint(2,"tag write: %r");
143+ close(fd);
144+}
145+
146+void
147+ctlwrite(Win *w, char *s)
148+{
149+ int n;
150+
151+ n = strlen(s);
152+ if(write(w->ctl, s, n) != n)
153+ threadprint(2,"write error to ctl file: %r");
154+}
155+
156+int
157+wdel(Win *w)
158+{
159+ if(write(w->ctl, "del\n", 4) != 4)
160+ return False;
161+ wdormant(w);
162+ close(w->ctl);
163+ w->ctl = -1;
164+ close(w->event);
165+ w->event = -1;
166+ return True;
167+}
168+
169+void
170+wname(Win *w, char *s)
171+{
172+ char buf[128];
173+
174+ sprint(buf, "name %s\n", s);
175+ ctlwrite(w, buf);
176+}
177+
178+void
179+wclean(Win *w)
180+{
181+ if(w->body)
182+ Bflush(w->body);
183+ ctlwrite(w, "clean\n");
184+}
185+
186+void
187+wdormant(Win *w)
188+{
189+ if(w->addr >= 0){
190+ close(w->addr);
191+ w->addr = -1;
192+ }
193+ if(w->body != nil){
194+ Bterm(w->body);
195+ w->body = nil;
196+ }
197+ if(w->data >= 0){
198+ close(w->data);
199+ w->data = -1;
200+ }
201+}
202+
203+int
204+getec(Win *w)
205+{
206+ if(w->nbuf == 0){
207+ w->nbuf = read(w->event, w->buf, sizeof w->buf);
208+ if(w->nbuf <= 0)
209+ threadprint(2,"event read error: %r");
210+ w->bufp = w->buf;
211+ }
212+ w->nbuf--;
213+ return *w->bufp++;
214+}
215+
216+int
217+geten(Win *w)
218+{
219+ int n, c;
220+
221+ n = 0;
222+ while('0'<=(c=getec(w)) && c<='9')
223+ n = n*10+(c-'0');
224+ if(c != ' ')
225+ threadprint(2, "event number syntax");
226+ return n;
227+}
228+
229+int
230+geter(Win *w, char *buf, int *nb)
231+{
232+ Rune r;
233+ int n;
234+
235+ r = getec(w);
236+ buf[0] = r;
237+ n = 1;
238+ if(r < Runeself)
239+ goto Return;
240+ while(!fullrune(buf, n))
241+ buf[n++] = getec(w);
242+ chartorune(&r, buf);
243+ Return:
244+ *nb = n;
245+ return r;
246+}
247+
248+
249+void
250+wevent(Win *w, Event *e)
251+{
252+ int i, nb;
253+
254+ e->c1 = getec(w);
255+ e->c2 = getec(w);
256+ e->q0 = geten(w);
257+ e->q1 = geten(w);
258+ e->flag = geten(w);
259+ e->nr = geten(w);
260+ if(e->nr > EVENTSIZE)
261+ threadprint(2, "wevent: event string too long");
262+ e->nb = 0;
263+ for(i=0; i<e->nr; i++){
264+ e->r[i] = geter(w, e->b+e->nb, &nb);
265+ e->nb += nb;
266+ }
267+ e->r[e->nr] = 0;
268+ e->b[e->nb] = 0;
269+ if(getec(w) != '\n')
270+ threadprint(2, "wevent: event syntax 2");
271+}
272+
273+void
274+wslave(Win *w, Channel *ce)
275+{
276+ Event e;
277+
278+ while(recv(ce, &e) >= 0)
279+ wevent(w, &e);
280+}
281+
282+void
283+wwriteevent(Win *w, Event *e)
284+{
285+ threadprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
286+}
287+
288+int
289+wreadall(Win *w, char **sp)
290+{
291+ char *s;
292+ int m, na, n;
293+
294+ if(w->body != nil)
295+ Bterm(w->body);
296+ openbody(w, OREAD);
297+ s = nil;
298+ na = 0;
299+ n = 0;
300+ for(;;){
301+ if(na < n+512){
302+ na += 1024;
303+ s = erealloc(s, na+1);
304+ }
305+ m = Bread(w->body, s+n, na-n);
306+ if(m <= 0)
307+ break;
308+ n += m;
309+ }
310+ s[n] = 0;
311+ Bterm(w->body);
312+ w->body = nil;
313+ *sp = s;
314+ return n;
315+}
acme/bin/source/adict/adict.c+591−0
@@ -0,0 +1,591 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include "win.h"
6+#include "adict.h"
7+
8+enum
9+{
10+ STACK = 8192,
11+};
12+
13+char *prog = "adict";
14+char *lprog = "/bin/adict";
15+char *xprog = "/bin/dict";
16+char *dict, *pattern, *curaddr[MAXMATCH], *curone, *args[6], buffer[80];
17+char abuffer[80], fbuffer[80], pbuffer[80];
18+int curindex, count, Eopen, Mopen;
19+Win Mwin, Ewin, Dwin;
20+
21+void openwin(char*, char*, Win*, int);
22+void handle(Win*, int);
23+void rexec(void*);
24+void pexec(void*);
25+int getaddr(char*);
26+
27+void
28+usage(void)
29+{
30+ fprint(2, "usage: %s [-d dictname] [pattern]\n", argv0);
31+ threadexitsall(nil);
32+}
33+
34+int mainstacksize = STACK;
35+
36+void
37+threadmain(int argc, char** argv)
38+{
39+ ARGBEGIN{
40+ case 'd':
41+ dict = strdup(ARGF());
42+ break;
43+ default:
44+ usage();
45+ }ARGEND
46+
47+ /* if running as other name, note that fact */
48+ if(access(argv0, AEXIST) == 0)
49+ lprog = argv0;
50+
51+ switch(argc){
52+ case 1:
53+ pattern = pbuffer;
54+ strcpy(pattern,argv[0]);
55+ if(dict == nil)
56+ dict = "pgw";
57+ break;
58+ case 0:
59+ break;
60+ default:
61+ usage();
62+ }
63+
64+ if ((dict == nil) && (pattern == nil))
65+ openwin(prog,"", &Dwin, Dictwin);
66+ if (pattern == nil)
67+ openwin(prog,"",&Ewin, Entrywin);
68+ if ((count = getaddr(pattern)) <= 1)
69+ openwin(prog,"Prev Next", &Ewin, Entrywin);
70+ else
71+ openwin(prog, "", &Mwin, Matchwin);
72+}
73+
74+static int
75+procrexec(char *xprog, ...)
76+{
77+ int fpipe[2];
78+ void *rexarg[4];
79+ Channel *c;
80+ va_list va;
81+ int i;
82+ char *p;
83+
84+ pipe(fpipe);
85+ va_start(va, xprog);
86+ p = xprog;
87+ for(i=0; p && i+1<nelem(args); i++){
88+ args[i] = p;
89+ p = va_arg(va, char*);
90+ }
91+ args[i] = nil;
92+
93+ c = chancreate(sizeof(ulong), 0);
94+ rexarg[0] = xprog;
95+ rexarg[1] = args;
96+ rexarg[2] = fpipe;
97+ rexarg[3] = c;
98+
99+ proccreate(rexec, rexarg, STACK);
100+ recvul(c);
101+ chanfree(c);
102+ close(fpipe[1]);
103+ return fpipe[0];
104+}
105+
106+int
107+getaddr(char *pattern)
108+{
109+ /* Get char offset into dictionary of matches. */
110+
111+ int fd, i;
112+ Biobuf inbuf;
113+ char *bufptr;
114+char *obuf;
115+
116+ if (pattern == nil) {
117+ curone = nil;
118+ curindex = 0;
119+ curaddr[curindex] = nil;
120+ return 0;
121+ }
122+
123+ sprint(buffer,"/%s/A", pattern);
124+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
125+ Binit(&inbuf, fd, OREAD);
126+ i = 0;
127+ curindex = 0;
128+ while ((bufptr = Brdline(&inbuf, '\n')) != nil && (i < (MAXMATCH-1))) {
129+ bufptr[Blinelen(&inbuf)-1] = 0;
130+obuf=bufptr;
131+ while (bufptr[0] != '#' && bufptr[0] != 0) bufptr++;
132+if(bufptr[0] == 0)
133+ print("whoops buf «%s»\n", obuf);
134+ curaddr[i] = malloc(strlen(bufptr));
135+ strcpy(curaddr[i], bufptr);
136+ i++;
137+ }
138+ curaddr[i] = nil;
139+ if (i == MAXMATCH)
140+ fprint(2, "Too many matches!\n");
141+ Bterm(&inbuf);
142+ close(fd);
143+
144+ curone = curaddr[curindex];
145+ return(i);
146+}
147+
148+char*
149+getpattern(char *addr)
150+{
151+ /* Get the pattern corresponding to an absolute address.*/
152+ int fd;
153+ char *res, *t;
154+
155+ res = nil;
156+ sprint(buffer,"%sh", addr);
157+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
158+ if (read(fd, pbuffer, 80) > 80)
159+ fprint(2, "Error in getting addres from dict.\n");
160+ else {
161+ t = pbuffer;
162+ /* remove trailing whitespace, newline */
163+ if (t != nil){
164+ while(*t != 0 && *t != '\n')
165+ t++;
166+ if(t == 0 && t > pbuffer)
167+ t--;
168+ while(t >= pbuffer && (*t==' ' || *t=='\n' || *t=='\t' || *t=='\r'))
169+ *t-- = 0;
170+ }
171+ res = pbuffer;
172+ }
173+ close(fd);
174+ return(res);
175+}
176+
177+char*
178+chgaddr(int dir)
179+{
180+ /* Increment or decrement the current address (curone). */
181+
182+ int fd;
183+ char *res, *t;
184+
185+ res = nil;
186+ if (dir < 0)
187+ sprint(buffer,"%s-a", curone);
188+ else
189+ sprint(buffer,"%s+a", curone);
190+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
191+ if (read(fd, abuffer, 80) > 80)
192+ fprint(2, "Error in getting addres from dict.\n");
193+ else {
194+ res = abuffer;
195+ while (*res != '#') res++;
196+ t = res;
197+ while ((*t != '\n') && (t != nil)) t++;
198+ if (t != nil) *t = 0;
199+ }
200+ close(fd);
201+ return(res);
202+}
203+
204+void
205+dispdicts(Win *cwin)
206+{
207+ /* Display available dictionaries in window. */
208+
209+ int fd, nb, i;
210+ char buf[1024], *t;
211+
212+ fd = procrexec(xprog, "-d", "?", nil);
213+ wreplace(cwin, "0,$","",0); /* Clear window */
214+ while ((nb = read(fd, buf, 1024)) > 0) {
215+ t = buf;
216+ i = 0;
217+ if (strncmp("Usage", buf, 5) == 0) { /* Remove first line. */
218+ while (t[0] != '\n') {
219+ t++;
220+ i++;
221+ }
222+ t++;
223+ i++;
224+ }
225+ wwritebody(cwin, t, nb-i);
226+ }
227+ close(fd);
228+ wclean(cwin);
229+}
230+
231+void
232+dispentry(Win *cwin)
233+{
234+ /* Display the current selection in window. */
235+
236+ int fd, nb;
237+ char buf[BUFSIZE];
238+
239+ if (curone == nil) {
240+ if (pattern != nil) {
241+ sprint(buf,"Pattern not found.\n");
242+ wwritebody(cwin, buf, 19);
243+ wclean(cwin);
244+ }
245+ return;
246+ }
247+ sprint(buffer,"%sp", curone);
248+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
249+ wreplace(cwin, "0,$","",0); /* Clear window */
250+ while ((nb = read(fd, buf, BUFSIZE)) > 0) {
251+ wwritebody(cwin, buf, nb);
252+ }
253+ close(fd);
254+ wclean(cwin);
255+}
256+
257+void
258+dispmatches(Win *cwin)
259+{
260+ /* Display the current matches. */
261+
262+ int fd, nb;
263+ char buf[BUFSIZE];
264+
265+ sprint(buffer,"/%s/H", pattern);
266+ fd = procrexec(xprog, "-d", dict, "-c", buffer, nil);
267+ while ((nb = read(fd, buf, BUFSIZE)) > 0)
268+ wwritebody(cwin, buf, nb);
269+ close(fd);
270+ wclean(cwin);
271+}
272+
273+char*
274+format(char *s)
275+{
276+ /* Format a string to be written in window tag. Acme doesn't like */
277+ /* non alpha-num's in the tag line. */
278+
279+ char *t, *h;
280+
281+ t = fbuffer;
282+ if (s == nil) {
283+ *t = 0;
284+ return t;
285+ }
286+ strcpy(t, s);
287+ h = t;
288+ while (*t != 0) {
289+ if (!(((*t >= 'a') && (*t <= 'z')) ||
290+ ((*t >= 'A') && (*t <= 'Z')) ||
291+ ((*t >= '0') && (*t <= '9'))))
292+ *t = '_';
293+ t++;
294+ }
295+ if (strlen(h) > MAXTAG)
296+ h[MAXTAG] = 0;
297+ if (strcmp(s,h) == 0) return s;
298+ return h;
299+}
300+
301+void
302+openwin(char *name, char *buttons, Win *twin, int wintype)
303+{
304+ char buf[80];
305+
306+ wnew(twin);
307+ if (wintype == Dictwin)
308+ sprint(buf,"%s",name);
309+ else
310+ if ((wintype == Entrywin) && (count > 1))
311+ sprint(buf,"%s/%s/%s/%d",name, dict, format(pattern), curindex+1);
312+ else
313+ sprint(buf,"%s/%s/%s",name, dict, format(pattern));
314+ wname(twin, buf);
315+ wtagwrite(twin, buttons, strlen(buttons));
316+ wclean(twin);
317+ wdormant(twin);
318+ if (wintype == Dictwin)
319+ dispdicts(twin);
320+ if (wintype == Matchwin) {
321+ Mopen = True;
322+ dispmatches(twin);
323+ }
324+ if (wintype == Entrywin) {
325+ Eopen = True;
326+ dispentry(twin);
327+ }
328+ handle(twin, wintype);
329+}
330+
331+void
332+vopenwin(void *v)
333+{
334+ void **arg;
335+ char *name, *buttons;
336+ Win *twin;
337+ int wintype;
338+
339+ arg = v;
340+ name = arg[0];
341+ buttons = arg[1];
342+ twin = arg[2];
343+ wintype = (int)arg[3];
344+ sendul(arg[4], 0);
345+
346+ openwin(name, buttons, twin, wintype);
347+ threadexits(nil);
348+}
349+
350+void
351+procopenwin(char *name, char *buttons, Win *twin, int wintype)
352+{
353+ void *arg[5];
354+ Channel *c;
355+
356+ c = chancreate(sizeof(ulong), 0);
357+ arg[0] = name;
358+ arg[1] = buttons;
359+ arg[2] = twin;
360+ arg[3] = (void*)wintype;
361+ arg[4] = c;
362+ proccreate(vopenwin, arg, STACK);
363+ recvul(c);
364+ chanfree(c);
365+}
366+
367+void
368+rexec(void *v)
369+{
370+ void **arg;
371+ char *prog;
372+ char **args;
373+ int *fd;
374+ Channel *c;
375+
376+ arg = v;
377+ prog = arg[0];
378+ args = arg[1];
379+ fd = arg[2];
380+ c = arg[3];
381+
382+ rfork(RFENVG|RFFDG);
383+ dup(fd[1], 1);
384+ close(fd[1]);
385+ close(fd[0]);
386+ procexec(c, prog, args);
387+ fprint(2, "Remote pipe execution failed: %s %r\n", prog);
388+abort();
389+ threadexits(nil);
390+}
391+
392+void
393+pexec(void *v)
394+{
395+ void **arg;
396+ char *prog;
397+ char **args;
398+ Channel *c;
399+
400+ arg = v;
401+ prog = arg[0];
402+ args = arg[1];
403+ c = arg[2];
404+
405+ procexec(c, prog, args);
406+ fprint(2, "Remote execution failed: %s %r\n", prog);
407+abort();
408+ threadexits(nil);
409+}
410+
411+void
412+procpexec(char *prog, char **args)
413+{
414+ void *rexarg[4];
415+ Channel *c;
416+
417+ c = chancreate(sizeof(ulong), 0);
418+ rexarg[0] = prog;
419+ rexarg[1] = args;
420+ rexarg[2] = c;
421+
422+ proccreate(pexec, rexarg, STACK);
423+ recvul(c);
424+ chanfree(c);
425+}
426+
427+void
428+kill(void)
429+{
430+ /* Kill all processes related to this one. */
431+ int fd;
432+
433+ sprint(buffer, "/proc/%d/notepg", getpid());
434+ fd = open(buffer, OWRITE);
435+ rfork(RFNOTEG);
436+ write(fd, "kill", 4);
437+}
438+
439+int
440+command(char *com, Win *w, int wintype)
441+{
442+ char *buf;
443+
444+ if (strncmp(com, "Del", 3) == 0) {
445+ switch(wintype){
446+ case Entrywin:
447+ if (wdel(w)) {
448+ Eopen = False;
449+ threadexits(nil);
450+ }
451+ break;
452+ case Dictwin:
453+ if (wdel(w))
454+ threadexits(nil);
455+ break;
456+ case Matchwin:
457+ kill();
458+ if (Eopen)
459+ if (~wdel(&Ewin)) /* Remove the entry window */
460+ wdel(&Ewin);
461+ if (!wdel(w))
462+ wdel(w);
463+ threadexits(nil);
464+ break;
465+ }
466+ return True;
467+ }
468+ if (strncmp(com, "Next", 4) == 0){
469+ if (curone != nil) {
470+ curone = chgaddr(1);
471+ buf = getpattern(curone);
472+ sprint(buffer,"%s/%s/%s", prog, dict, format(buf));
473+ wname(w, buffer);
474+ dispentry(w);
475+ }
476+ return True;
477+ }
478+ if (strncmp(com, "Prev",4) == 0){
479+ if (curone != nil) {
480+ curone = chgaddr(-1);
481+ buf = getpattern(curone);
482+ sprint(buffer,"%s/%s/%s", prog, dict, format(buf));
483+ wname(w, buffer);
484+ dispentry(w);
485+ }
486+ return True;
487+ }
488+ if (strncmp(com, "Nmatch",6) == 0){
489+ if (curaddr[++curindex] == nil)
490+ curindex = 0;
491+ curone = curaddr[curindex];
492+ if (curone != nil) {
493+ sprint(buffer,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1);
494+ wname(w, buffer);
495+ dispentry(w);
496+ }
497+ return True;
498+ }
499+ return False;
500+}
501+
502+void
503+handle(Win *w, int wintype)
504+{
505+ Event e, e2, ea, etoss;
506+ char *s, *t, buf[80];
507+ int tmp, na;
508+
509+ while (True) {
510+ wevent(w, &e);
511+ switch(e.c2){
512+ default:
513+ /* fprint(2,"unknown message %c%c\n", e.c1, e.c2); */
514+ break;
515+ case 'i':
516+ /* fprint(2,"'%s' inserted in tag at %d\n", e.b, e.q0);*/
517+ break;
518+ case 'I':
519+ /* fprint(2,"'%s' inserted in body at %d\n", e.b, e.q0);*/
520+ break;
521+ case 'd':
522+ /* fprint(2, "'%s' deleted in tag at %d\n", e.b, e.q0);*/
523+ break;
524+ case 'D':
525+ /* fprint(2, "'%s' deleted in body at %d\n", e.b, e.q0);*/
526+ break;
527+ case 'x':
528+ case 'X': /* Execute command. */
529+ if (e.flag & 2)
530+ wevent(w, &e2);
531+ if(e.flag & 8){
532+ wevent(w, &ea);
533+ wevent(w, &etoss);
534+ na = ea.nb;
535+ } else
536+ na = 0;
537+ s = e.b;
538+ if ((e.flag & 2) && e.nb == 0)
539+ s = e2.b;
540+ if(na){
541+ t = malloc(strlen(s)+1+na+1);
542+ snprint(t, strlen(s)+1+na+1, "%s %s", s, ea.b);
543+ s = t;
544+ }
545+ /* if it's a long message, it can't be for us anyway */
546+ if(!command(s, w, wintype)) /* send it back */
547+ wwriteevent(w, &e);
548+ if(na)
549+ free(s);
550+ break;
551+ case 'l':
552+ case 'L': /* Look for something. */
553+ if (e.flag & 2)
554+ wevent(w, &e);
555+ wclean(w); /* Set clean bit. */
556+ if (wintype == Dictwin) {
557+ strcpy(buf, e.b);
558+ args[0] = lprog;
559+ args[1] = "-d";
560+ args[2] = buf;
561+ args[3] = nil;
562+ procpexec(lprog, args); /* New adict with chosen dict. */
563+ }
564+ if (wintype == Entrywin) {
565+ strcpy(buf, e.b);
566+ args[0] = lprog;
567+ args[1] = "-d";
568+ args[2] = dict;
569+ args[3] = buf;
570+ args[4] = nil;
571+ procpexec(lprog, args); /* New adict with chosen pattern. */
572+ }
573+ if (wintype == Matchwin) {
574+ tmp = atoi(e.b) - 1;
575+ if ((tmp >= 0) && (tmp < MAXMATCH) && (curaddr[tmp] != nil)) {
576+ curindex = tmp;
577+ curone = curaddr[curindex];
578+ /* Display selected match. */
579+ if (Eopen) {
580+ sprint(buf,"%s/%s/%s/%d",prog,dict,format(pattern),curindex+1);
581+ wname(&Ewin, buf);
582+ dispentry(&Ewin);
583+ }
584+ else
585+ procopenwin(prog,"Nmatch Prev Next", &Ewin, Entrywin);
586+ }
587+ }
588+ break;
589+ }
590+ }
591+}
acme/bin/source/adict/adict.h+10−0
@@ -0,0 +1,10 @@
1+enum
2+{
3+ Matchwin,
4+ Entrywin,
5+ Dictwin
6+};
7+
8+#define MAXTAG 20
9+#define MAXMATCH 100
10+#define BUFSIZE 4096
acme/bin/source/adict/man+26−0
@@ -0,0 +1,26 @@
1+adict [-d dictionary] [pattern]
2+
3+ adict with no arguments opens a window that displays all the currently
4+available dictionaries. To select a dictionary, click the right mouse button on
5+its name.
6+
7+-d dictionary Opens a window that interfaces to the specified dictionary. To
8+ look up a word, enter it in the window, and click the right mouse button on it.
9+
10+[pattern] If no dictionary is specified, adict looks up the pattern in "oed" (Oxford
11+ English Dictionary). If more than one entry is found, adict opens a window
12+ displaying the headers of the matching entries. To display a particular entry
13+ click the right mouse button on the number to its left.
14+
15+Quit Exit and remove all windows associated with this one.
16+
17+Nmatch Display the next matching entry.
18+
19+Next Display the next entry in the dictionary.
20+
21+Prev Display the previous entry in the dictionary.
22+
23+ Nmatch works independently of Prev and Next.
24+
25+ Any word in the window displaying an entry can be looked up in the selected
26+dictionary by clicking the right mouse button on that word.
acme/bin/source/adict/mkfile+11−0
@@ -0,0 +1,11 @@
1+</$objtype/mkfile
2+
3+TARG=adict
4+
5+HFILES=win.h
6+
7+OFILES=adict.$O\
8+ win.$O\
9+
10+BIN= /acme/bin/$objtype
11+</sys/src/cmd/mkone
acme/bin/source/adict/win.c+315−0
@@ -0,0 +1,315 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include "win.h"
6+
7+void*
8+erealloc(void *p, uint n)
9+{
10+ p = realloc(p, n);
11+ if(p == nil)
12+ fprint(2, "realloc failed: %r");
13+ return p;
14+}
15+
16+void
17+wnew(Win *w)
18+{
19+ char buf[12];
20+
21+ w->ctl = open("/mnt/acme/new/ctl", ORDWR);
22+ if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
23+ fprint (2, "can't open window ctl file: %r");
24+ ctlwrite(w, "noscroll\n");
25+ w->winid = atoi(buf);
26+ w->event = openfile(w, "event");
27+ w->addr = -1; /* will be opened when needed */
28+ w->body = nil;
29+ w->data = -1;
30+}
31+
32+int
33+openfile(Win *w, char *f)
34+{
35+ char buf[64];
36+ int fd;
37+
38+ sprint(buf, "/mnt/acme/%d/%s", w->winid, f);
39+ fd = open(buf, ORDWR|OCEXEC);
40+ if(fd < 0)
41+ fprint (2,"can't open window %s file: %r", f);
42+ return fd;
43+}
44+
45+void
46+openbody(Win *w, int mode)
47+{
48+ char buf[64];
49+
50+ sprint(buf, "/mnt/acme/%d/body", w->winid);
51+ w->body = Bopen(buf, mode|OCEXEC);
52+ if(w->body == nil)
53+ fprint(2,"can't open window body file: %r");
54+}
55+
56+void
57+wwritebody(Win *w, char *s, int n)
58+{
59+ if(w->body == nil)
60+ openbody(w, OWRITE);
61+ if(Bwrite(w->body, s, n) != n)
62+ fprint(2,"write error to window: %r");
63+ Bflush(w->body);
64+}
65+
66+void
67+wreplace(Win *w, char *addr, char *repl, int nrepl)
68+{
69+ if(w->addr < 0)
70+ w->addr = openfile(w, "addr");
71+ if(w->data < 0)
72+ w->data = openfile(w, "data");
73+ if(write(w->addr, addr, strlen(addr)) < 0){
74+ fprint(2, "mail: warning: badd address %s:%r\n", addr);
75+ return;
76+ }
77+ if(write(w->data, repl, nrepl) != nrepl)
78+ fprint(2, "writing data: %r");
79+}
80+
81+static int
82+nrunes(char *s, int nb)
83+{
84+ int i, n;
85+ Rune r;
86+
87+ n = 0;
88+ for(i=0; i<nb; n++)
89+ i += chartorune(&r, s+i);
90+ return n;
91+}
92+
93+void
94+wread(Win *w, uint q0, uint q1, char *data)
95+{
96+ int m, n, nr;
97+ char buf[256];
98+
99+ if(w->addr < 0)
100+ w->addr = openfile(w, "addr");
101+ if(w->data < 0)
102+ w->data = openfile(w, "data");
103+ m = q0;
104+ while(m < q1){
105+ n = sprint(buf, "#%d", m);
106+ if(write(w->addr, buf, n) != n)
107+ fprint(2,"writing addr: %r");
108+ n = read(w->data, buf, sizeof buf);
109+ if(n <= 0)
110+ fprint(2,"reading data: %r");
111+ nr = nrunes(buf, n);
112+ while(m+nr >q1){
113+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
114+ --nr;
115+ }
116+ if(n == 0)
117+ break;
118+ memmove(data, buf, n);
119+ data += n;
120+ *data = 0;
121+ m += nr;
122+ }
123+}
124+
125+void
126+wselect(Win *w, char *addr)
127+{
128+ if(w->addr < 0)
129+ w->addr = openfile(w, "addr");
130+ if(write(w->addr, addr, strlen(addr)) < 0)
131+ fprint(2,"writing addr");
132+ ctlwrite(w, "dot=addr\n");
133+}
134+
135+void
136+wtagwrite(Win *w, char *s, int n)
137+{
138+ int fd;
139+
140+ fd = openfile(w, "tag");
141+ if(write(fd, s, n) != n)
142+ fprint(2,"tag write: %r");
143+ close(fd);
144+}
145+
146+void
147+ctlwrite(Win *w, char *s)
148+{
149+ int n;
150+
151+ n = strlen(s);
152+ if(write(w->ctl, s, n) != n)
153+ fprint(2,"write error to ctl file: %r");
154+}
155+
156+int
157+wdel(Win *w)
158+{
159+ if(write(w->ctl, "del\n", 4) != 4)
160+ return False;
161+ wdormant(w);
162+ close(w->ctl);
163+ w->ctl = -1;
164+ close(w->event);
165+ w->event = -1;
166+ return True;
167+}
168+
169+void
170+wname(Win *w, char *s)
171+{
172+ char buf[128];
173+
174+ sprint(buf, "name %s\n", s);
175+ ctlwrite(w, buf);
176+}
177+
178+void
179+wclean(Win *w)
180+{
181+ if(w->body)
182+ Bflush(w->body);
183+ ctlwrite(w, "clean\n");
184+}
185+
186+void
187+wdormant(Win *w)
188+{
189+ if(w->addr >= 0){
190+ close(w->addr);
191+ w->addr = -1;
192+ }
193+ if(w->body != nil){
194+ Bterm(w->body);
195+ w->body = nil;
196+ }
197+ if(w->data >= 0){
198+ close(w->data);
199+ w->data = -1;
200+ }
201+}
202+
203+int
204+getec(Win *w)
205+{
206+ if(w->nbuf == 0){
207+ w->nbuf = read(w->event, w->buf, sizeof w->buf);
208+ if(w->nbuf <= 0)
209+ fprint(2,"event read error: %r");
210+ w->bufp = w->buf;
211+ }
212+ w->nbuf--;
213+ return *w->bufp++;
214+}
215+
216+int
217+geten(Win *w)
218+{
219+ int n, c;
220+
221+ n = 0;
222+ while('0'<=(c=getec(w)) && c<='9')
223+ n = n*10+(c-'0');
224+ if(c != ' ')
225+ fprint(2, "event number syntax");
226+ return n;
227+}
228+
229+int
230+geter(Win *w, char *buf, int *nb)
231+{
232+ Rune r;
233+ int n;
234+
235+ r = getec(w);
236+ buf[0] = r;
237+ n = 1;
238+ if(r < Runeself)
239+ goto Return;
240+ while(!fullrune(buf, n))
241+ buf[n++] = getec(w);
242+ chartorune(&r, buf);
243+ Return:
244+ *nb = n;
245+ return r;
246+}
247+
248+
249+void
250+wevent(Win *w, Event *e)
251+{
252+ int i, nb;
253+
254+ e->c1 = getec(w);
255+ e->c2 = getec(w);
256+ e->q0 = geten(w);
257+ e->q1 = geten(w);
258+ e->flag = geten(w);
259+ e->nr = geten(w);
260+ if(e->nr > EVENTSIZE)
261+ fprint(2, "wevent: event string too long");
262+ e->nb = 0;
263+ for(i=0; i<e->nr; i++){
264+ e->r[i] = geter(w, e->b+e->nb, &nb);
265+ e->nb += nb;
266+ }
267+ e->r[e->nr] = 0;
268+ e->b[e->nb] = 0;
269+ if(getec(w) != '\n')
270+ fprint(2, "wevent: event syntax 2");
271+}
272+
273+void
274+wslave(Win *w, Channel *ce)
275+{
276+ Event e;
277+
278+ while(recv(ce, &e) >= 0)
279+ wevent(w, &e);
280+}
281+
282+void
283+wwriteevent(Win *w, Event *e)
284+{
285+ fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
286+}
287+
288+int
289+wreadall(Win *w, char **sp)
290+{
291+ char *s;
292+ int m, na, n;
293+
294+ if(w->body != nil)
295+ Bterm(w->body);
296+ openbody(w, OREAD);
297+ s = nil;
298+ na = 0;
299+ n = 0;
300+ for(;;){
301+ if(na < n+512){
302+ na += 1024;
303+ s = erealloc(s, na+1);
304+ }
305+ m = Bread(w->body, s+n, na-n);
306+ if(m <= 0)
307+ break;
308+ n += m;
309+ }
310+ s[n] = 0;
311+ Bterm(w->body);
312+ w->body = nil;
313+ *sp = s;
314+ return n;
315+}
acme/bin/source/adict/win.h+59−0
@@ -0,0 +1,59 @@
1+enum
2+{
3+ False,
4+ True,
5+ EVENTSIZE=256,
6+};
7+
8+
9+typedef struct Event Event;
10+struct Event
11+{
12+ int c1;
13+ int c2;
14+ int q0;
15+ int q1;
16+ int flag;
17+ int nb;
18+ int nr;
19+ char b[EVENTSIZE*UTFmax+1];
20+ Rune r[EVENTSIZE+1];
21+};
22+
23+
24+typedef struct Win Win;
25+struct Win
26+{
27+ int winid;
28+ int addr;
29+ Biobuf *body;
30+ int ctl;
31+ int data;
32+ int event;
33+ char buf[512];
34+ char *bufp;
35+ int nbuf;
36+};
37+
38+int dead(Win*);
39+void wnew(Win*);
40+void wwritebody(Win*, char *s, int n);
41+void wread(Win*, uint, uint, char*);
42+void wclean(Win*);
43+void wname(Win*, char*);
44+void wdormant(Win*);
45+void wevent(Win*, Event*);
46+void wtagwrite(Win*, char*, int);
47+void wwriteevent(Win*, Event*);
48+void wslave(Win*, Channel*); /* chan(Event) */
49+void wreplace(Win*, char*, char*, int);
50+void wselect(Win*, char*);
51+int wdel(Win*);
52+int wreadall(Win*, char**);
53+
54+void ctlwrite(Win*, char*);
55+int getec(Win*);
56+int geten(Win*);
57+int geter(Win*, char*, int*);
58+int openfile(Win*, char*);
59+void openbody(Win*, int);
acme/bin/source/mkfile+27−0
@@ -0,0 +1,27 @@
1+</$objtype/mkfile
2+
3+TARG=\
4+ mkwnew\
5+ spout\
6+
7+OFILES=
8+HFILES=
9+LIB=
10+
11+DIRS=win
12+
13+BIN=../$objtype
14+
15+</sys/src/cmd/mkmany
16+
17+all:V: all.dirs
18+install:V: install.dirs
19+clean:V: clean.dirs
20+nuke:V: nuke.dirs
21+
22+%.dirs:VQ:
23+ for (i in $DIRS) @{
24+ echo mk $i
25+ cd $i
26+ mk $stem
27+ }
acme/bin/source/mkwnew.6+0−0

Binary file not shown.

acme/bin/source/mkwnew.8+0−0

Binary file not shown.

acme/bin/source/mkwnew.c+45−0
@@ -0,0 +1,45 @@
1+#include <u.h>
2+#include <libc.h>
3+
4+void
5+main(int argc, char *argv[])
6+{
7+ int i, fd, pid, n;
8+ char wdir[256];
9+ int dflag;
10+
11+ dflag = 0;
12+ ARGBEGIN{
13+ case 'd':
14+ dflag = 1;
15+ break;
16+ default:
17+ fprint(2, "usage: wnew [-d] [label]\n");
18+ }ARGEND
19+
20+ pid = getpid();
21+ wdir[0] = '\0';
22+ if(!dflag)
23+ getwd(wdir, sizeof wdir);
24+ if(argc>0)
25+ for(i=0; i<argc; i++)
26+ snprint(wdir, sizeof wdir, "%s%c%s", wdir, i==0? '/' : '-', argv[i]);
27+ else
28+ snprint(wdir, sizeof wdir, "%s/-win", wdir);
29+
30+ if((fd = open("/dev/wnew", ORDWR)) < 0)
31+ sysfatal("wnew: can't open /dev/wnew: %r");
32+
33+ if(fprint(fd, "%d %s", pid, wdir+dflag) < 0)
34+ sysfatal("wnew: can't create window: %r");
35+
36+ if(seek(fd, 0, 0) != 0)
37+ sysfatal("wnew: can't seek: %r");
38+
39+ if((n=read(fd, wdir, sizeof wdir-1)) < 0)
40+ sysfatal("wnew: can't read window id: %r");
41+ wdir[n] = '\0';
42+
43+ print("%s\n", wdir);
44+ exits(nil);
45+}
acme/bin/source/spout.6+0−0

Binary file not shown.

acme/bin/source/spout.8+0−0

Binary file not shown.

acme/bin/source/spout.c+123−0
@@ -0,0 +1,123 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <ctype.h>
4+#include <bio.h>
5+
6+void spout(int, char*);
7+
8+Biobuf bout;
9+
10+void
11+main(int argc, char *argv[])
12+{
13+ int i, fd;
14+
15+ Binit(&bout, 1, OWRITE);
16+ if(argc == 1)
17+ spout(0, "");
18+ else
19+ for(i=1; i<argc; i++){
20+ fd = open(argv[i], OREAD);
21+ if(fd < 0){
22+ fprint(2, "spell: can't open %s: %r\n", argv[i]);
23+ continue;
24+ }
25+ spout(fd, argv[i]);
26+ close(fd);
27+ }
28+ exits(nil);
29+}
30+
31+Biobuf b;
32+
33+void
34+spout(int fd, char *name)
35+{
36+ char *s, *t, *w;
37+ Rune r;
38+ int inword, wordchar;
39+ int n, wn, wid, c, m;
40+ char buf[1024];
41+
42+ Binit(&b, fd, OREAD);
43+ n = 0;
44+ wn = 0;
45+ while((s = Brdline(&b, '\n')) != nil){
46+ if(s[0] == '.')
47+ for(c=0; c<3 && *s>' '; c++){
48+ n++;
49+ s++;
50+ }
51+ inword = 0;
52+ w = s;
53+ t = s;
54+ do{
55+ c = *(uchar*)t;
56+ if(c < Runeself)
57+ wid = 1;
58+ else{
59+ wid = chartorune(&r, t);
60+ c = r;
61+ }
62+ wordchar = 0;
63+ if(isalpha(c))
64+ wordchar = 1;
65+ if(inword && !wordchar){
66+ if(c=='\'' && isalpha(t[1]))
67+ goto Continue;
68+ m = t-w;
69+ if(m > 1){
70+ memmove(buf, w, m);
71+ buf[m] = 0;
72+ Bprint(&bout, "%s:#%d,#%d:%s\n", name, wn, n, buf);
73+ }
74+ inword = 0;
75+ }else if(!inword && wordchar){
76+ wn = n;
77+ w = t;
78+ inword = 1;
79+ }
80+ if(c=='\\' && (isalpha(t[1]) || t[1]=='(')){
81+ switch(t[1]){
82+ case '(':
83+ m = 4;
84+ break;
85+ case 'f':
86+ if(t[2] == '(')
87+ m = 5;
88+ else
89+ m = 3;
90+ break;
91+ case 's':
92+ if(t[2] == '+' || t[2]=='-'){
93+ if(t[3] == '(')
94+ m = 6;
95+ else
96+ m = 4;
97+ }else{
98+ if(t[2] == '(')
99+ m = 5;
100+ else if(t[2]=='1' || t[2]=='2' || t[2]=='3')
101+ m = 4;
102+ else
103+ m = 3;
104+ }
105+ break;
106+ default:
107+ m = 2;
108+ }
109+ while(m-- > 0){
110+ if(*t == '\n')
111+ break;
112+ n++;
113+ t++;
114+ }
115+ continue;
116+ }
117+ Continue:
118+ n++;
119+ t += wid;
120+ }while(c != '\n');
121+ }
122+ Bterm(&b);
123+}
acme/bin/source/win/6.out+0−0

Binary file not shown.

acme/bin/source/win/8.out+0−0

Binary file not shown.

acme/bin/source/win/dat.h+98−0
@@ -0,0 +1,98 @@
1+typedef struct Fsevent Fsevent;
2+typedef struct Event Event;
3+typedef struct Message Message;
4+typedef struct Window Window;
5+
6+enum
7+{
8+ STACK = 8192,
9+ NPIPEDATA = 8000,
10+ NPIPE = NPIPEDATA+32,
11+ /* EVENTSIZE is really 256 in acme, but we use events internally and want bigger buffers */
12+ EVENTSIZE = 8192,
13+ NEVENT = 5,
14+};
15+
16+struct Fsevent
17+{
18+ int type;
19+ void *r;
20+};
21+
22+struct Event
23+{
24+ int c1;
25+ int c2;
26+ int q0;
27+ int q1;
28+ int flag;
29+ int nb;
30+ int nr;
31+ char b[EVENTSIZE*UTFmax+1];
32+ Rune r[EVENTSIZE+1];
33+};
34+
35+struct Window
36+{
37+ /* file descriptors */
38+ int ctl;
39+ int event;
40+ int addr;
41+ int data;
42+ int body;
43+
44+ /* event input */
45+ char buf[512];
46+ char *bufp;
47+ int nbuf;
48+ Event e[NEVENT];
49+
50+ int id;
51+ int open;
52+ Channel *cevent;
53+};
54+
55+extern Window* newwindow(void);
56+extern int winopenfile(Window*, char*);
57+extern void wintagwrite(Window*, char*, int);
58+extern void winname(Window*, char*);
59+extern void winwriteevent(Window*, Event*);
60+extern int winread(Window*, uint, uint, char*);
61+extern int windel(Window*, int);
62+extern void wingetevent(Window*, Event*);
63+extern void wineventproc(void*);
64+extern void winclean(Window*);
65+extern int winselect(Window*, char*, int);
66+extern int winsetaddr(Window*, char*, int);
67+extern void windormant(Window*);
68+extern void winsetdump(Window*, char*, char*);
69+extern void winsetdir(Window*, char*, char*);
70+
71+extern void ctlprint(int, char*, ...);
72+extern void* emalloc(uint);
73+extern char* estrdup(char*);
74+extern char* estrstrdup(char*, char*);
75+extern char* egrow(char*, char*, char*);
76+extern char* eappend(char*, char*, char*);
77+extern void error(char*, ...);
78+
79+extern void startpipe(void);
80+extern void sendit(char*);
81+extern void execevent(Window *w, Event *e, int (*)(Window*, char*));
82+
83+extern void mountcons(void);
84+extern void fsloop(void*);
85+
86+extern int newpipewin(int, char*);
87+extern void startpipe(void);
88+extern int pipecommand(Window*, char*);
89+extern void pipectl(void*);
90+
91+#pragma varargck argpos error 1
92+#pragma varargck argpos ctlprint 2
93+
94+extern char *wname;
95+extern char *wdir;
96+extern Window *win;
97+extern Channel *fschan, *writechan;
98+
acme/bin/source/win/fs.6+0−0

Binary file not shown.

acme/bin/source/win/fs.8+0−0

Binary file not shown.

acme/bin/source/win/fs.c+190−0
@@ -0,0 +1,190 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <fcall.h>
4+#include <thread.h>
5+#include <9p.h>
6+#include "dat.h"
7+
8+Channel *fschan;
9+Channel *writechan;
10+
11+static File *devcons, *devnew, *devwdir;
12+
13+static void
14+fsread(Req *r)
15+{
16+ Fsevent e;
17+
18+ if(r->fid->file == devnew){
19+ if(r->fid->aux==nil){
20+ respond(r, "phase error");
21+ return;
22+ }
23+ readstr(r, r->fid->aux);
24+ respond(r, nil);
25+ return;
26+ }
27+
28+ if(r->fid->file == devwdir){
29+ readstr(r, wdir);
30+ respond(r, nil);
31+ return;
32+ }
33+
34+ e.type = 'r';
35+ e.r = r;
36+ send(fschan, &e);
37+}
38+
39+static void
40+fsflush(Req *r)
41+{
42+ Fsevent e;
43+
44+ e.type = 'f';
45+ e.r = r;
46+ send(fschan, &e);
47+}
48+
49+static void
50+fswrite(Req *r)
51+{
52+ static Event *e[4];
53+ Event *ep;
54+ int nb, wid, pid;
55+ Rune rune;
56+ char *s, *se, *d, *p;
57+ static int n, partial;
58+
59+ if(r->fid->file == devnew){
60+ if(r->fid->aux){
61+ respond(r, "already created a window");
62+ return;
63+ }
64+ s = emalloc(r->ifcall.count+1);
65+ memmove(s, r->ifcall.data, r->ifcall.count);
66+ s[r->ifcall.count] = 0;
67+ pid = strtol(s, &p, 0);
68+ if(*p==' ')
69+ p++;
70+ nb = newpipewin(pid, p);
71+ free(s);
72+ s = emalloc(32);
73+ sprint(s, "%lud", (ulong)nb);
74+ r->fid->aux = s;
75+ r->ofcall.count = r->ifcall.count;
76+ respond(r, nil);
77+ return;
78+ }
79+
80+ if(r->fid->file == devwdir){
81+ s = emalloc(r->ifcall.count+1);
82+ memmove(s, r->ifcall.data, r->ifcall.count);
83+ s[r->ifcall.count] = 0;
84+ if(s[0] == '#' || s[0] == '/'){
85+ free(wdir);
86+ wdir = s;
87+ } else {
88+ wdir = eappend(wdir, "/", s);
89+ free(s);
90+ }
91+ cleanname(wdir);
92+ winsetdir(win, wdir, wname);
93+ respond(r, nil);
94+ return;
95+ }
96+
97+ if(r->fid->file != devcons){
98+ respond(r, "bug in fswrite");
99+ return;
100+ }
101+
102+ /* init buffer rings */
103+ if(e[0] == nil){
104+ for(n=0; n<nelem(e); n++){
105+ e[n] = emalloc(sizeof(Event));
106+ e[n]->c1 = 'S';
107+ }
108+ }
109+
110+ s = r->ifcall.data;
111+ se = s + r->ifcall.count;
112+
113+ while((nb = (se - s)) > 0){
114+ assert(partial >= 0);
115+ if((partial+nb) > EVENTSIZE)
116+ nb = EVENTSIZE - partial;
117+
118+ /* fill buffer */
119+ ep = e[n++ % nelem(e)];
120+ memmove(ep->b+partial, s, nb);
121+ partial += nb;
122+ s += nb;
123+
124+ /* check full runes, remove null bytes */
125+ ep->nr = ep->nb = 0;
126+ for(d = p = ep->b; partial > 0; partial -= wid, p += wid){
127+ if(*p == '\0'){
128+ wid = 1;
129+ continue;
130+ }
131+
132+ if(!fullrune(p, partial))
133+ break;
134+
135+ wid = chartorune(&rune, p);
136+ runetochar(d, &rune);
137+ d += wid;
138+
139+ ep->nr++;
140+ ep->nb += wid;
141+ }
142+
143+ /* put partial reminder onto next buffer */
144+ if(partial > 0)
145+ memmove(e[n % nelem(e)]->b, p, partial);
146+
147+ /* send buffer when not empty */
148+ if(ep->nb > 0){
149+ ep->b[ep->nb] = '\0';
150+ sendp(win->cevent, ep);
151+ recvp(writechan);
152+ }
153+ }
154+
155+ r->ofcall.count = r->ifcall.count;
156+ respond(r, nil);
157+}
158+
159+void
160+fsdestroyfid(Fid *fid)
161+{
162+ if(fid->aux)
163+ free(fid->aux);
164+}
165+
166+Srv fs = {
167+.read= fsread,
168+.write= fswrite,
169+.flush= fsflush,
170+.destroyfid= fsdestroyfid,
171+.leavefdsopen= 1,
172+};
173+
174+void
175+mountcons(void)
176+{
177+ fschan = chancreate(sizeof(Fsevent), 0);
178+ writechan = chancreate(sizeof(void*), 0);
179+ fs.tree = alloctree("win", "win", DMDIR|0555, nil);
180+ devcons = createfile(fs.tree->root, "cons", "win", 0666, nil);
181+ if(devcons == nil)
182+ sysfatal("creating /dev/cons: %r");
183+ devnew = createfile(fs.tree->root, "wnew", "win", 0666, nil);
184+ if(devnew == nil)
185+ sysfatal("creating /dev/wnew: %r");
186+ devwdir = createfile(fs.tree->root, "wdir", "win", 0666, nil);
187+ if(devwdir == nil)
188+ sysfatal("creating /dev/wdir: %r");
189+ threadpostmountsrv(&fs, nil, "/dev", MBEFORE);
190+}
acme/bin/source/win/main.6+0−0

Binary file not shown.

acme/bin/source/win/main.8+0−0

Binary file not shown.

acme/bin/source/win/main.c+643−0
@@ -0,0 +1,643 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include <fcall.h>
6+#include <9p.h>
7+#include <ctype.h>
8+#include "dat.h"
9+
10+void mainctl(void*);
11+void startcmd(char *[], int*);
12+void stdout2body(void*);
13+
14+int debug;
15+int notepg;
16+int eraseinput;
17+int dirty = 0;
18+
19+char *wname;
20+char *wdir;
21+Window *win; /* the main window */
22+
23+void
24+usage(void)
25+{
26+ fprint(2, "usage: win [command]\n");
27+ threadexitsall("usage");
28+}
29+
30+void
31+threadmain(int argc, char *argv[])
32+{
33+ int i, j;
34+ char buf[1024], **av;
35+
36+ quotefmtinstall();
37+ rfork(RFNAMEG);
38+ ARGBEGIN{
39+ case 'd':
40+ debug = 1;
41+ chatty9p++;
42+ break;
43+ case 'e':
44+ eraseinput = 1;
45+ break;
46+ case 'D':
47+{extern int _threaddebuglevel;
48+ _threaddebuglevel = 1<<20;
49+}
50+ }ARGEND
51+
52+ if(argc == 0){
53+ av = emalloc(3*sizeof(char*));
54+ av[0] = "rc";
55+ av[1] = "-i";
56+ }else{
57+ av = argv;
58+ }
59+ wname = utfrrune(av[0], '/');
60+ if(wname)
61+ wname++;
62+ else
63+ wname = av[0];
64+ if(getwd(buf, sizeof buf) == 0)
65+ wdir = "/";
66+ else
67+ wdir = buf;
68+ wdir = estrdup(wdir);
69+ win = newwindow();
70+ snprint(buf, sizeof buf, "%d", win->id);
71+ putenv("winid", buf);
72+ winsetdir(win, wdir, wname);
73+ wintagwrite(win, "Send Noscroll", 5+8);
74+ threadcreate(mainctl, win, STACK);
75+ mountcons();
76+ threadcreate(fsloop, nil, STACK);
77+ startpipe();
78+ startcmd(av, &notepg);
79+
80+ strcpy(buf, "win");
81+ j = 3;
82+ for(i=0; i<argc && j+1+strlen(argv[i])+1<sizeof buf; i++){
83+ strcpy(buf+j, " ");
84+ strcpy(buf+j+1, argv[i]);
85+ j += 1+strlen(argv[i]);
86+ }
87+
88+ ctlprint(win->ctl, "scroll");
89+ winsetdump(win, wdir, buf);
90+}
91+
92+int
93+EQUAL(char *s, char *t)
94+{
95+ while(tolower(*s) == tolower(*t++))
96+ if(*s++ == '\0')
97+ return 1;
98+ return 0;
99+}
100+
101+int
102+command(Window *w, char *s)
103+{
104+ while(*s==' ' || *s=='\t' || *s=='\n')
105+ s++;
106+ if(strcmp(s, "Delete")==0 || strcmp(s, "Del")==0){
107+ windel(w, 1);
108+ threadexitsall(nil);
109+ return 1;
110+ }
111+ if(EQUAL(s, "scroll")){
112+ ctlprint(w->ctl, "scroll\nshow");
113+ return 1;
114+ }
115+ if(EQUAL(s, "noscroll")){
116+ ctlprint(w->ctl, "noscroll");
117+ return 1;
118+ }
119+ return 0;
120+}
121+
122+static long
123+utfncpy(char *to, char *from, int n)
124+{
125+ char *end, *e;
126+
127+ e = to+n;
128+ if(to >= e)
129+ return 0;
130+ end = memccpy(to, from, '\0', e - to);
131+ if(end == nil){
132+ end = e;
133+ if(end[-1]&0x80){
134+ if(end-2>=to && (end[-2]&0xE0)==0xC0)
135+ return end-to;
136+ if(end-3>=to && (end[-3]&0xF0)==0xE0)
137+ return end-to;
138+ while(end>to && (*--end&0xC0)==0x80)
139+ ;
140+ }
141+ }else
142+ end--;
143+ return end - to;
144+}
145+
146+/* sendinput and fsloop run in the same proc (can't interrupt each other). */
147+static Req *q;
148+static Req **eq;
149+static int
150+__sendinput(Window *w, ulong q0, ulong q1)
151+{
152+ char *s, *t;
153+ int n, nb, eofchar;
154+ static int partial;
155+ static char tmp[UTFmax];
156+ Req *r;
157+ Rune rune;
158+
159+ if(!q)
160+ return 0;
161+
162+ r = q;
163+ n = 0;
164+ if(partial){
165+ Partial:
166+ nb = partial;
167+ if(nb > r->ifcall.count)
168+ nb = r->ifcall.count;
169+ memmove(r->ofcall.data, tmp, nb);
170+ if(nb!=partial)
171+ memmove(tmp, tmp+nb, partial-nb);
172+ partial -= nb;
173+ q = r->aux;
174+ if(q == nil)
175+ eq = &q;
176+ r->aux = nil;
177+ r->ofcall.count = nb;
178+ if(debug)
179+ fprint(2, "satisfy read with partial\n");
180+ respond(r, nil);
181+ return n;
182+ }
183+ if(q0==q1)
184+ return 0;
185+ s = emalloc((q1-q0)*UTFmax+1);
186+ n = winread(w, q0, q1, s);
187+ s[n] = '\0';
188+ t = strpbrk(s, "\n\004");
189+ if(t == nil){
190+ free(s);
191+ return 0;
192+ }
193+ r = q;
194+ eofchar = 0;
195+ if(*t == '\004'){
196+ eofchar = 1;
197+ *t = '\0';
198+ }else
199+ *++t = '\0';
200+ nb = utfncpy((char*)r->ofcall.data, s, r->ifcall.count);
201+ if(nb==0 && s<t && r->ifcall.count > 0){
202+ partial = utfncpy(tmp, s, UTFmax);
203+ assert(partial > 0);
204+ chartorune(&rune, tmp);
205+ partial = runelen(rune);
206+ free(s);
207+ n = 1;
208+ goto Partial;
209+ }
210+ n = utfnlen(r->ofcall.data, nb);
211+ if(nb==strlen(s) && eofchar)
212+ n++;
213+ r->ofcall.count = nb;
214+ q = r->aux;
215+ if(q == nil)
216+ eq = &q;
217+ r->aux = nil;
218+ if(debug)
219+ fprint(2, "read returns %lud-%lud: %.*q\n", q0, q0+n, n, r->ofcall.data);
220+ respond(r, nil);
221+ return n;
222+}
223+
224+static int
225+_sendinput(Window *w, ulong q0, ulong *q1)
226+{
227+ char buf[32];
228+ int n;
229+
230+ n = __sendinput(w, q0, *q1);
231+ if(!n || !eraseinput)
232+ return n;
233+ /* erase q0 to q0+n */
234+ sprint(buf, "#%lud,#%lud", q0, q0+n);
235+ winsetaddr(w, buf, 0);
236+ write(w->data, buf, 0);
237+ *q1 -= n;
238+ return 0;
239+}
240+
241+int
242+sendinput(Window *w, ulong q0, ulong *q1)
243+{
244+ ulong n;
245+ Req *oq;
246+
247+ n = 0;
248+ do {
249+ oq = q;
250+ n += _sendinput(w, q0+n, q1);
251+ } while(q != oq);
252+ return n;
253+}
254+
255+Event esendinput;
256+void
257+fsloop(void*)
258+{
259+ Fsevent e;
260+ Req **l, *r;
261+
262+ eq = &q;
263+ memset(&esendinput, 0, sizeof esendinput);
264+ esendinput.c1 = 'C';
265+ for(;;){
266+ while(recv(fschan, &e) == -1)
267+ ;
268+ r = e.r;
269+ switch(e.type){
270+ case 'r':
271+ *eq = r;
272+ r->aux = nil;
273+ eq = &r->aux;
274+ /* call sendinput with hostpt and endpt */
275+ sendp(win->cevent, &esendinput);
276+ break;
277+ case 'f':
278+ for(l=&q; *l; l=&(*l)->aux){
279+ if(*l == r->oldreq){
280+ *l = (*l)->aux;
281+ if(*l == nil)
282+ eq = l;
283+ respond(r->oldreq, "interrupted");
284+ break;
285+ }
286+ }
287+ respond(r, nil);
288+ break;
289+ }
290+ }
291+}
292+
293+void
294+sendit(char *s)
295+{
296+// char tmp[32];
297+
298+ write(win->body, s, strlen(s));
299+/*
300+ * RSC: The problem here is that other procs can call sendit,
301+ * so we lose our single-threadedness if we call sendinput.
302+ * In fact, we don't even have the right queue memory,
303+ * I think that we'll get a write event from the body write above,
304+ * and we can do the sendinput then, from our single thread.
305+ *
306+ * I still need to figure out how to test this assertion for
307+ * programs that use /srv/win*
308+ *
309+ winselect(win, "$", 0);
310+ seek(win->addr, 0UL, 0);
311+ if(read(win->addr, tmp, 2*12) == 2*12)
312+ hostpt += sendinput(win, hostpt, atol(tmp), );
313+ */
314+}
315+
316+void
317+execevent(Window *w, Event *e, int (*command)(Window*, char*))
318+{
319+ Event *ea, *e2;
320+ int n, na, len, needfree;
321+ char *s, *t;
322+
323+ ea = nil;
324+ e2 = nil;
325+ if(e->flag & 2)
326+ e2 = recvp(w->cevent);
327+ if(e->flag & 8){
328+ ea = recvp(w->cevent);
329+ na = ea->nb;
330+ recvp(w->cevent);
331+ }else
332+ na = 0;
333+
334+ needfree = 0;
335+ s = e->b;
336+ if(e->nb==0 && (e->flag&2)){
337+ s = e2->b;
338+ e->q0 = e2->q0;
339+ e->q1 = e2->q1;
340+ e->nb = e2->nb;
341+ }
342+ if(e->nb==0 && e->q0<e->q1){
343+ /* fetch data from window */
344+ s = emalloc((e->q1-e->q0)*UTFmax+2);
345+ n = winread(w, e->q0, e->q1, s);
346+ s[n] = '\0';
347+ needfree = 1;
348+ }else
349+ if(na){
350+ t = emalloc(strlen(s)+1+na+2);
351+ sprint(t, "%s %s", s, ea->b);
352+ if(needfree)
353+ free(s);
354+ s = t;
355+ needfree = 1;
356+ }
357+
358+ /* if it's a known command, do it */
359+ /* if it's a long message, it can't be for us anyway */
360+ if(!command(w, s) && s[0]!='\0'){ /* send it as typed text */
361+ /* if it's a built-in from the tag, send it back */
362+ if(e->flag & 1)
363+ fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
364+ else{ /* send text to main window */
365+ len = strlen(s);
366+ if(len>0 && s[len-1]!='\n' && s[len-1]!='\004'){
367+ if(!needfree){
368+ /* if(needfree), we left room for a newline before */
369+ t = emalloc(len+2);
370+ strcpy(t, s);
371+ s = t;
372+ needfree = 1;
373+ }
374+ s[len++] = '\n';
375+ s[len] = '\0';
376+ }
377+ sendit(s);
378+ }
379+ }
380+ if(needfree)
381+ free(s);
382+}
383+
384+int
385+hasboundary(Rune *r, int nr)
386+{
387+ int i;
388+
389+ for(i=0; i<nr; i++)
390+ if(r[i]=='\n' || r[i]=='\004')
391+ return 1;
392+ return 0;
393+}
394+
395+void
396+mainctl(void *v)
397+{
398+ Window *w;
399+ Event *e;
400+ int delta, pendingS, pendingK;
401+ ulong hostpt, endpt;
402+ char tmp[32];
403+
404+ w = v;
405+ proccreate(wineventproc, w, STACK);
406+
407+ hostpt = 0;
408+ endpt = 0;
409+ winsetaddr(w, "0", 0);
410+ pendingS = 0;
411+ pendingK = 0;
412+ for(;;){
413+ if(debug)
414+ fprint(2, "input range %lud-%lud\n", hostpt, endpt);
415+ e = recvp(w->cevent);
416+ if(debug)
417+ fprint(2, "msg: %C %C %d %d %d %d %q\n",
418+ e->c1 ? e->c1 : ' ', e->c2 ? e->c2 : ' ', e->q0, e->q1, e->flag, e->nb, e->b);
419+ switch(e->c1){
420+ default:
421+ Unknown:
422+ fprint(2, "unknown message %c%c\n", e->c1, e->c2);
423+ break;
424+
425+ case 'C': /* input needed for /dev/cons */
426+ if(pendingS)
427+ pendingK = 1;
428+ else
429+ hostpt += sendinput(w, hostpt, &endpt);
430+ break;
431+
432+ case 'S': /* output to stdout */
433+ sprint(tmp, "#%lud", hostpt);
434+ winsetaddr(w, tmp, 0);
435+ write(w->data, e->b, e->nb);
436+ pendingS += e->nr;
437+ break;
438+
439+ case 'E': /* write to tag or body; body happens due to sendit */
440+ delta = e->q1-e->q0;
441+ if(e->c2=='I'){
442+ endpt += delta;
443+ if(e->q0 < hostpt)
444+ hostpt += delta;
445+ else
446+ hostpt += sendinput(w, hostpt, &endpt);
447+ break;
448+ }
449+ if(!islower(e->c2))
450+ fprint(2, "win msg: %C %C %d %d %d %d %q\n",
451+ e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b);
452+ break;
453+
454+ case 'F': /* generated by our actions (specifically case 'S' above) */
455+ delta = e->q1-e->q0;
456+ if(e->c2=='D'){
457+ /* we know about the delete by _sendinput */
458+ break;
459+ }
460+ if(e->c2=='I'){
461+ pendingS -= e->q1 - e->q0;
462+ if(pendingS < 0)
463+ fprint(2, "win: pendingS = %d\n", pendingS);
464+ if(e->q0 != hostpt)
465+ fprint(2, "win: insert at %d expected %lud\n", e->q0, hostpt);
466+ endpt += delta;
467+ hostpt += delta;
468+ sendp(writechan, nil);
469+ if(pendingS == 0 && pendingK){
470+ pendingK = 0;
471+ hostpt += sendinput(w, hostpt, &endpt);
472+ }
473+ break;
474+ }
475+ if(!islower(e->c2))
476+ fprint(2, "win msg: %C %C %d %d %d %d %q\n",
477+ e->c1, e->c2, e->q0, e->q1, e->flag, e->nb, e->b);
478+ break;
479+
480+ case 'K':
481+ delta = e->q1-e->q0;
482+ switch(e->c2){
483+ case 'D':
484+ endpt -= delta;
485+ if(e->q1 < hostpt)
486+ hostpt -= delta;
487+ else if(e->q0 < hostpt)
488+ hostpt = e->q0;
489+ break;
490+ case 'I':
491+ delta = e->q1 - e->q0;
492+ endpt += delta;
493+ if(endpt < e->q1) /* just in case */
494+ endpt = e->q1;
495+ if(e->q0 < hostpt)
496+ hostpt += delta;
497+ if(e->nr>0 && e->r[e->nr-1]==0x7F){
498+ write(notepg, "interrupt", 9);
499+ hostpt = endpt;
500+ break;
501+ }
502+ if(e->q0 >= hostpt
503+ && hasboundary(e->r, e->nr)){
504+ /*
505+ * If we are between the S message (which
506+ * we processed by inserting text in the
507+ * window) and the F message notifying us
508+ * that the text has been inserted, then our
509+ * impression of the hostpt and acme's
510+ * may be different. This could be seen if you
511+ * hit enter a bunch of times in a con
512+ * session. To work around the unreliability,
513+ * only send input if we don't have an S pending.
514+ * The same race occurs between when a character
515+ * is typed and when we get notice of it, but
516+ * since characters tend to be typed at the end
517+ * of the buffer, we don't run into it. There's
518+ * no workaround possible for this typing race,
519+ * since we can't tell when the user has typed
520+ * something but we just haven't been notified.
521+ */
522+ if(pendingS)
523+ pendingK = 1;
524+ else
525+ hostpt += sendinput(w, hostpt, &endpt);
526+ }
527+ break;
528+ }
529+ break;
530+
531+ case 'M': /* mouse */
532+ delta = e->q1-e->q0;
533+ switch(e->c2){
534+ case 'x':
535+ case 'X':
536+ execevent(w, e, command);
537+ break;
538+
539+ case 'l': /* reflect all searches back to acme */
540+ case 'L':
541+ if(e->flag & 2)
542+ recvp(w->cevent);
543+ winwriteevent(w, e);
544+ break;
545+
546+ case 'I':
547+ endpt += delta;
548+ if(e->q0 < hostpt)
549+ hostpt += delta;
550+ else
551+ hostpt += sendinput(w, hostpt, &endpt);
552+ break;
553+
554+ case 'D':
555+ endpt -= delta;
556+ if(e->q1 < hostpt)
557+ hostpt -= delta;
558+ else if(e->q0 < hostpt)
559+ hostpt = e->q0;
560+ break;
561+ case 'd': /* modify away; we don't care */
562+ case 'i':
563+ break;
564+
565+ default:
566+ goto Unknown;
567+ }
568+ }
569+ }
570+}
571+
572+enum
573+{
574+ NARGS = 100,
575+ NARGCHAR = 8*1024,
576+ EXECSTACK = STACK+(NARGS+1)*sizeof(char*)+NARGCHAR
577+};
578+
579+struct Exec
580+{
581+ char **argv;
582+ Channel *cpid;
583+};
584+
585+int
586+lookinbin(char *s)
587+{
588+ if(s[0] == '/')
589+ return 0;
590+ if(s[0]=='.' && s[1]=='/')
591+ return 0;
592+ if(s[0]=='.' && s[1]=='.' && s[2]=='/')
593+ return 0;
594+ return 1;
595+}
596+
597+/* adapted from mail. not entirely free of details from that environment */
598+void
599+execproc(void *v)
600+{
601+ struct Exec *e;
602+ char *cmd, **av;
603+ Channel *cpid;
604+
605+ e = v;
606+ rfork(RFCFDG|RFNOTEG);
607+ av = e->argv;
608+ close(0);
609+ open("/dev/cons", OREAD);
610+ close(1);
611+ open("/dev/cons", OWRITE);
612+ dup(1, 2);
613+ cpid = e->cpid;
614+ free(e);
615+ procexec(cpid, av[0], av);
616+ if(lookinbin(av[0])){
617+ cmd = estrstrdup("/bin/", av[0]);
618+ procexec(cpid, cmd, av);
619+ }
620+ error("can't exec %s: %r", av[0]);
621+}
622+
623+void
624+startcmd(char *argv[], int *notepg)
625+{
626+ struct Exec *e;
627+ Channel *cpid;
628+ char buf[64];
629+ int pid;
630+
631+ e = emalloc(sizeof(struct Exec));
632+ e->argv = argv;
633+ cpid = chancreate(sizeof(ulong), 0);
634+ e->cpid = cpid;
635+ sprint(buf, "/mnt/wsys/%d", win->id);
636+ bind(buf, "/dev/acme", MREPL);
637+ proccreate(execproc, e, EXECSTACK);
638+ do
639+ pid = recvul(cpid);
640+ while(pid == -1);
641+ sprint(buf, "/proc/%d/notepg", pid);
642+ *notepg = open(buf, OWRITE);
643+}
acme/bin/source/win/mkfile+25−0
@@ -0,0 +1,25 @@
1+</$objtype/mkfile
2+
3+TARG=win
4+OFILES=\
5+ fs.$O\
6+ main.$O\
7+ pipe.$O\
8+ util.$O\
9+ win.$O
10+
11+HFILES=dat.h
12+LIB=/$objtype/lib/lib9p.a
13+
14+BIN=/acme/bin/$objtype
15+</sys/src/cmd/mkone
16+
17+UPDATE=\
18+ mkfile\
19+ $HFILES\
20+ ${OFILES:%.$O=%.c}\
21+ ${TARG:%=/acme/bin/$objtype/%}\
22+
23+syms:V:
24+ 8c -a main.c >syms
25+ 8c -aa util.c win.c >>syms
acme/bin/source/win/pipe.6+0−0

Binary file not shown.

acme/bin/source/win/pipe.8+0−0

Binary file not shown.

acme/bin/source/win/pipe.c+175−0
@@ -0,0 +1,175 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <fcall.h>
4+#include <thread.h>
5+#include <9p.h>
6+#include "dat.h"
7+
8+typedef struct Wpid Wpid;
9+struct Wpid
10+{
11+ int pid;
12+ Window *w;
13+ Wpid *next;
14+};
15+
16+void pipectl(void*);
17+
18+int pipefd;
19+Wpid *wpid;
20+int snarffd;
21+Channel *newpipechan;
22+
23+int
24+newpipewin(int pid, char *p)
25+{
26+ int id;
27+ Window *w;
28+ Wpid *wp;
29+
30+ w = newwindow();
31+ winname(w, p);
32+ wintagwrite(w, "Send ", 5);
33+ wp = emalloc(sizeof(Wpid));
34+ wp->pid = pid;
35+ wp->w = w;
36+ wp->next = wpid; /* BUG: this happens in fsread proc (we don't use wpid, so it's okay) */
37+ wpid = wp;
38+ id = w->id;
39+ sendp(newpipechan, w);
40+ return id;
41+}
42+
43+int
44+pipecommand(Window *w, char *s)
45+{
46+ ulong q0, q1;
47+ char tmp[32], *t;
48+ int n, k;
49+
50+ while(*s==' ' || *s=='\t' || *s=='\n')
51+ s++;
52+ if(strcmp(s, "Delete")==0){
53+ windel(w, 1);
54+ threadexits(nil);
55+ return 1;
56+ }
57+ if(strcmp(s, "Del")==0){
58+ if(windel(w, 0))
59+ threadexits(nil);
60+ return 1;
61+ }
62+ if(strcmp(s, "Send") == 0){
63+ if(w->addr < 0)
64+ w->addr = winopenfile(w, "addr");
65+ ctlprint(w->ctl, "addr=dot\n");
66+ seek(w->addr, 0UL, 0);
67+ if(read(w->addr, tmp, 2*12) == 2*12){
68+ q0 = atol(tmp+0*12);
69+ q1 = atol(tmp+1*12);
70+ if(q0 == q1){
71+ t = nil;
72+ k = 0;
73+ if(snarffd > 0){
74+ seek(0, snarffd, 0);
75+ for(;;){
76+ t = realloc(t, k+8192+2);
77+ if(t == nil)
78+ error("alloc failed: %r\n");
79+ n = read(snarffd, t+k, 8192);
80+ if(n <= 0)
81+ break;
82+ k += n;
83+ }
84+ t[k] = 0;
85+ }
86+ }else{
87+ t = emalloc((q1-q0)*UTFmax+2);
88+ winread(w, q0, q1, t);
89+ k = strlen(t);
90+ }
91+ if(t!=nil && t[0]!='\0'){
92+ if(t[k-1]!='\n' && t[k-1]!='\004'){
93+ t[k++] = '\n';
94+ t[k] = '\0';
95+ }
96+ sendit(t);
97+ }
98+ free(t);
99+ }
100+ return 1;
101+ }
102+ return 0;
103+}
104+
105+void
106+pipectl(void *v)
107+{
108+ Window *w;
109+ Event *e;
110+
111+ w = v;
112+ proccreate(wineventproc, w, STACK);
113+
114+ windormant(w);
115+ winsetaddr(w, "0", 0);
116+ for(;;){
117+ e = recvp(w->cevent);
118+ switch(e->c1){
119+ default:
120+ Unknown:
121+ fprint(2, "unknown message %c%c\n", e->c1, e->c2);
122+ break;
123+
124+ case 'E': /* write to body; can't affect us */
125+ break;
126+
127+ case 'F': /* generated by our actions; ignore */
128+ break;
129+
130+ case 'K': /* ignore */
131+ break;
132+
133+ case 'M':
134+ switch(e->c2){
135+ case 'x':
136+ case 'X':
137+ execevent(w, e, pipecommand);
138+ break;
139+
140+ case 'l': /* reflect all searches back to acme */
141+ case 'L':
142+ if(e->flag & 2)
143+ recvp(w->cevent);
144+ winwriteevent(w, e);
145+ break;
146+
147+ case 'I': /* modify away; we don't care */
148+ case 'i':
149+ case 'D':
150+ case 'd':
151+ break;
152+
153+ default:
154+ goto Unknown;
155+ }
156+ }
157+ }
158+}
159+
160+void
161+newpipethread(void*)
162+{
163+ Window *w;
164+
165+ while(w = recvp(newpipechan))
166+ threadcreate(pipectl, w, STACK);
167+}
168+
169+void
170+startpipe(void)
171+{
172+ newpipechan = chancreate(sizeof(Window*), 0);
173+ threadcreate(newpipethread, nil, STACK);
174+ snarffd = open("/dev/snarf", OREAD|OCEXEC);
175+}
acme/bin/source/win/util.6+0−0

Binary file not shown.

acme/bin/source/win/util.8+0−0

Binary file not shown.

acme/bin/source/win/util.c+90−0
@@ -0,0 +1,90 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include "dat.h"
6+
7+void*
8+emalloc(uint n)
9+{
10+ void *p;
11+
12+ p = malloc(n);
13+ if(p == nil)
14+ error("can't malloc: %r");
15+ memset(p, 0, n);
16+ return p;
17+}
18+
19+char*
20+estrdup(char *s)
21+{
22+ char *t;
23+
24+ t = emalloc(strlen(s)+1);
25+ strcpy(t, s);
26+ return t;
27+}
28+
29+char*
30+estrstrdup(char *s, char *t)
31+{
32+ char *u;
33+
34+ u = emalloc(strlen(s)+strlen(t)+1);
35+ sprint(u, "%s%s", s, t);
36+ return u;
37+}
38+
39+char*
40+eappend(char *s, char *sep, char *t)
41+{
42+ char *u;
43+
44+ if(t == nil)
45+ u = estrstrdup(s, sep);
46+ else{
47+ u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1);
48+ sprint(u, "%s%s%s", s, sep, t);
49+ }
50+ free(s);
51+ return u;
52+}
53+
54+char*
55+egrow(char *s, char *sep, char *t)
56+{
57+ s = eappend(s, sep, t);
58+ free(t);
59+ return s;
60+}
61+
62+void
63+error(char *fmt, ...)
64+{
65+ Fmt f;
66+ char buf[64];
67+ va_list arg;
68+
69+ fmtfdinit(&f, 2, buf, sizeof buf);
70+ fmtprint(&f, "win: ");
71+ va_start(arg, fmt);
72+ fmtvprint(&f, fmt, arg);
73+ va_end(arg);
74+ fmtprint(&f, "\n");
75+ fmtfdflush(&f);
76+ threadexitsall(buf);
77+}
78+
79+void
80+ctlprint(int fd, char *fmt, ...)
81+{
82+ int n;
83+ va_list arg;
84+
85+ va_start(arg, fmt);
86+ n = vfprint(fd, fmt, arg);
87+ va_end(arg);
88+ if(n <= 0)
89+ error("control file write error: %r");
90+}
acme/bin/source/win/win.6+0−0

Binary file not shown.

acme/bin/source/win/win.8+0−0

Binary file not shown.

acme/bin/source/win/win.c+273−0
@@ -0,0 +1,273 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include "dat.h"
6+
7+Window*
8+newwindow(void)
9+{
10+ char buf[12];
11+ Window *w;
12+
13+ w = emalloc(sizeof(Window));
14+ w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC);
15+ if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
16+ error("can't open window ctl file: %r");
17+ ctlprint(w->ctl, "noscroll\n");
18+ w->id = atoi(buf);
19+ w->event = winopenfile(w, "event");
20+ w->addr = winopenfile(w, "addr");
21+ w->body = winopenfile(w, "body");
22+ w->data = winopenfile(w, "data");
23+ w->cevent = chancreate(sizeof(Event*), 0);
24+ return w;
25+}
26+
27+void
28+winsetdump(Window *w, char *dir, char *cmd)
29+{
30+ if(dir != nil)
31+ ctlprint(w->ctl, "dumpdir %s\n", dir);
32+ if(cmd != nil)
33+ ctlprint(w->ctl, "dump %s\n", cmd);
34+}
35+
36+void
37+winsetdir(Window *w, char *dir, char *name)
38+{
39+ ctlprint(w->ctl, "dumpdir %s\n", dir);
40+ if(strcmp(dir, "/")==0)
41+ dir++;
42+ ctlprint(w->ctl, "name %s/-%s\n", dir, name);
43+}
44+
45+void
46+wineventproc(void *v)
47+{
48+ Window *w;
49+ int i;
50+
51+ w = v;
52+ for(i=0; ; i++){
53+ if(i >= NEVENT)
54+ i = 0;
55+ wingetevent(w, &w->e[i]);
56+ sendp(w->cevent, &w->e[i]);
57+ }
58+}
59+
60+int
61+winopenfile(Window *w, char *f)
62+{
63+ char buf[64];
64+ int fd;
65+
66+ sprint(buf, "/mnt/wsys/%d/%s", w->id, f);
67+ fd = open(buf, ORDWR|OCEXEC);
68+ if(fd < 0)
69+ error("can't open window file %s: %r", f);
70+ return fd;
71+}
72+
73+void
74+wintagwrite(Window *w, char *s, int n)
75+{
76+ int fd;
77+
78+ fd = winopenfile(w, "tag");
79+ if(write(fd, s, n) != n)
80+ error("tag write: %r");
81+ close(fd);
82+}
83+
84+void
85+winname(Window *w, char *s)
86+{
87+ ctlprint(w->ctl, "name %s\n", s);
88+}
89+
90+int
91+wingetec(Window *w)
92+{
93+ if(w->nbuf == 0){
94+ w->nbuf = read(w->event, w->buf, sizeof w->buf);
95+ if(w->nbuf <= 0){
96+ /* probably because window has exited, and only called by wineventproc, so just shut down */
97+ threadexits(nil);
98+ }
99+ w->bufp = w->buf;
100+ }
101+ w->nbuf--;
102+ return *w->bufp++;
103+}
104+
105+int
106+wingeten(Window *w)
107+{
108+ int n, c;
109+
110+ n = 0;
111+ while('0'<=(c=wingetec(w)) && c<='9')
112+ n = n*10+(c-'0');
113+ if(c != ' ')
114+ error("event number syntax");
115+ return n;
116+}
117+
118+int
119+wingeter(Window *w, char *buf, int *nb)
120+{
121+ Rune r;
122+ int n;
123+
124+ r = wingetec(w);
125+ buf[0] = r;
126+ n = 1;
127+ if(r >= Runeself) {
128+ while(!fullrune(buf, n))
129+ buf[n++] = wingetec(w);
130+ chartorune(&r, buf);
131+ }
132+ *nb = n;
133+ return r;
134+}
135+
136+void
137+wingetevent(Window *w, Event *e)
138+{
139+ int i, nb;
140+
141+ e->c1 = wingetec(w);
142+ e->c2 = wingetec(w);
143+ e->q0 = wingeten(w);
144+ e->q1 = wingeten(w);
145+ e->flag = wingeten(w);
146+ e->nr = wingeten(w);
147+ if(e->nr > EVENTSIZE)
148+ error("event string too long");
149+ e->nb = 0;
150+ for(i=0; i<e->nr; i++){
151+ e->r[i] = wingeter(w, e->b+e->nb, &nb);
152+ e->nb += nb;
153+ }
154+ e->r[e->nr] = 0;
155+ e->b[e->nb] = 0;
156+ if(wingetec(w) != '\n')
157+ error("event syntax error");
158+}
159+
160+void
161+winwriteevent(Window *w, Event *e)
162+{
163+ fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
164+}
165+
166+static int
167+nrunes(char *s, int nb)
168+{
169+ int i, n;
170+ Rune r;
171+
172+ n = 0;
173+ for(i=0; i<nb; n++)
174+ i += chartorune(&r, s+i);
175+ return n;
176+}
177+
178+int
179+winread(Window *w, uint q0, uint q1, char *data)
180+{
181+ int m, n, nr, nb;
182+ char buf[256];
183+
184+ if(w->addr < 0)
185+ w->addr = winopenfile(w, "addr");
186+ if(w->data < 0)
187+ w->data = winopenfile(w, "data");
188+ m = q0;
189+ nb = 0;
190+ while(m < q1){
191+ n = sprint(buf, "#%d", m);
192+ if(write(w->addr, buf, n) != n)
193+ error("error writing addr: %r");
194+ n = read(w->data, buf, sizeof buf);
195+ if(n < 0)
196+ error("reading data: %r");
197+ nr = nrunes(buf, n);
198+ while(m+nr >q1){
199+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
200+ --nr;
201+ }
202+ if(n == 0)
203+ break;
204+ memmove(data, buf, n);
205+ nb += n;
206+ data += n;
207+ *data = 0;
208+ m += nr;
209+ }
210+ return nb;
211+}
212+
213+void
214+windormant(Window *w)
215+{
216+ if(w->addr >= 0){
217+ close(w->addr);
218+ w->addr = -1;
219+ }
220+ if(w->body >= 0){
221+ close(w->body);
222+ w->body = -1;
223+ }
224+ if(w->data >= 0){
225+ close(w->data);
226+ w->data = -1;
227+ }
228+}
229+
230+int
231+windel(Window *w, int sure)
232+{
233+ if(sure)
234+ write(w->ctl, "delete\n", 7);
235+ else if(write(w->ctl, "del\n", 4) != 4)
236+ return 0;
237+ /* event proc will die due to read error from event file */
238+ windormant(w);
239+ close(w->ctl);
240+ w->ctl = -1;
241+ close(w->event);
242+ w->event = -1;
243+ return 1;
244+}
245+
246+void
247+winclean(Window *w)
248+{
249+ ctlprint(w->ctl, "clean\n");
250+}
251+
252+int
253+winsetaddr(Window *w, char *addr, int errok)
254+{
255+ if(w->addr < 0)
256+ w->addr = winopenfile(w, "addr");
257+ if(write(w->addr, addr, strlen(addr)) < 0){
258+ if(!errok)
259+ error("error writing addr(%s): %r", addr);
260+ return 0;
261+ }
262+ return 1;
263+}
264+
265+int
266+winselect(Window *w, char *addr, int errok)
267+{
268+ if(winsetaddr(w, addr, errok)){
269+ ctlprint(w->ctl, "dot=addr\n");
270+ return 1;
271+ }
272+ return 0;
273+}
acme/bin/unind+3−0
@@ -0,0 +1,3 @@
1+#!/bin/rc
2+
3+sed 's/^ //' $*
acme/bin/wnew+5−0
@@ -0,0 +1,5 @@
1+#!/bin/rc -e
2+
3+id=`{mkwnew $*}
4+cat >/mnt/acme/$id/body
5+echo clean >/mnt/acme/$id/ctl
acme/mail/guide+4−0
@@ -0,0 +1,4 @@
1+Mail stored
2+plumb /mail/box/$user/names
3+mail -'x' someaddress
4+mkbox /mail/box/$user/new_box
acme/mail/mkbox+11−0
@@ -0,0 +1,11 @@
1+#!/bin/rc
2+
3+for(i){
4+ if(! test -e $i){
5+ if(cp /dev/null $i){
6+ chmod 600 $i
7+ chmod +al $i
8+ }
9+ }
10+ if not echo $i already exists
11+}
acme/mail/readme+57−0
@@ -0,0 +1,57 @@
1+The Acme Mail program uses upas/fs to parse the mail box, and then
2+presents a file-browser-like user interface to reading and sending
3+messages. The Mail window presents each numbered message like the
4+contents of a directory presented one per line. If a message has a
5+Subject: line, that is shown indented on the following line.
6+Multipart MIME-encoded messages are presented in the obvious
7+hierarchical format.
8+
9+Mail uses upas/fs to access the mail box. By default it reads "mbox",
10+the standard user mail box. If Mail is given an argument, it is
11+passed to upas/fs as the name of the mail box (or upas/fs directory)
12+to open.
13+
14+Although Mail works if the plumber is not running, it's designed to be
15+run with plumbing enabled and many of its features work best if it is.
16+
17+The mailbox window has a few commands: Put writes back the mailbox;
18+Mail creates a new window in which to compose a message; and Delmesg
19+deletes messages by number. The number may be given as argument or
20+indicated by selecting the header line in the mailbox window.
21+(Delmesg does not expand null selections, in the interest of safety.)
22+
23+Clicking the right button on a message number opens it; clicking on
24+any of the subparts of a message opens that (and also opens the
25+message itself). Each message window has a few commands in the tag
26+with obvious names: Reply, Delmsg, etc. "Reply" replies to the single
27+sender of the message, "Reply all" or "Replyall" replies to everyone
28+in the From:, To:, and CC: lines.
29+
30+Message parts with recognized MIME types such as image/jpeg are sent
31+to the plumber for further dispatch. Acme Mail also listens to
32+messages on the seemail and showmail plumbing ports, to report the
33+arrival of new messages (highlighting the entry; right-click on the
34+entry to open the message) and open them if you right-click on the
35+face in the faces window.
36+
37+When composing a mail message or replying to a message, the first line
38+of the text is a list of recipients of the message. To:, and CC:, and BCC:
39+lines are interpreted in the usual way. Two other header lines are
40+special to Acme Mail:
41+ Include: file places a copy of file in the message as an
42+ inline MIME attachment.
43+ Attach: file places a copy of file in the message as a regular
44+ MIME attachment.
45+
46+Acme Mail uses these conventions when replying to messages,
47+constructing headers for the default behavior. You may edit these to
48+change behavior. Most important, when replying to a message Mail will
49+always Include: the original message; delete that line if you don't
50+want to include it.
51+
52+If the mailbox
53+ /mail/box/$user/outgoing
54+exists, Acme Mail will save your a copy of your outgoing messages
55+there. Attachments are described in the copy but not included.
56+
57+The -m mntpoint flag specifies a different mount point for /upas/fs.
acme/mail/src/6.out+0−0

Binary file not shown.

acme/mail/src/8.out+0−0

Binary file not shown.

acme/mail/src/dat.h+164−0
@@ -0,0 +1,164 @@
1+typedef struct Event Event;
2+typedef struct Exec Exec;
3+typedef struct Message Message;
4+typedef struct Window Window;
5+
6+enum
7+{
8+ STACK = 8192,
9+ EVENTSIZE = 256,
10+ NEVENT = 5,
11+};
12+
13+struct Event
14+{
15+ int c1;
16+ int c2;
17+ int q0;
18+ int q1;
19+ int flag;
20+ int nb;
21+ int nr;
22+ char b[EVENTSIZE*UTFmax+1];
23+ Rune r[EVENTSIZE+1];
24+};
25+
26+struct Window
27+{
28+ /* file descriptors */
29+ int ctl;
30+ int event;
31+ int addr;
32+ int data;
33+ Biobuf *body;
34+
35+ /* event input */
36+ char buf[512];
37+ char *bufp;
38+ int nbuf;
39+ Event e[NEVENT];
40+
41+ int id;
42+ int open;
43+ Channel *cevent;
44+};
45+
46+struct Message
47+{
48+ Window *w;
49+ int ctlfd;
50+ char *name;
51+ char *replyname;
52+ uchar opened;
53+ uchar dirty;
54+ uchar isreply;
55+ uchar deleted;
56+ uchar writebackdel;
57+ uchar tagposted;
58+ uchar recursed;
59+ uchar level;
60+
61+ /* header info */
62+ char *fromcolon; /* from header file; all rest are from info file */
63+ char *from;
64+ char *to;
65+ char *cc;
66+ char *replyto;
67+ char *date;
68+ char *subject;
69+ char *type;
70+ char *disposition;
71+ char *filename;
72+ char *digest;
73+
74+ Message *next; /* next in this mailbox */
75+ Message *prev; /* prev in this mailbox */
76+ Message *head; /* first subpart */
77+ Message *tail; /* last subpart */
78+};
79+
80+enum
81+{
82+ NARGS = 100,
83+ NARGCHAR = 8*1024,
84+ EXECSTACK = STACK+(NARGS+1)*sizeof(char*)+NARGCHAR
85+};
86+
87+struct Exec
88+{
89+ char *prog;
90+ char **argv;
91+ int p[2]; /* p[1] is write to program; p[0] set to prog fd 0*/
92+ int q[2]; /* q[0] is read from program; q[1] set to prog fd 1 */
93+ Channel *sync;
94+};
95+
96+extern Window* newwindow(void);
97+extern int winopenfile(Window*, char*);
98+extern void winopenbody(Window*, int);
99+extern void winclosebody(Window*);
100+extern void wintagwrite(Window*, char*, int);
101+extern void winname(Window*, char*);
102+extern void winwriteevent(Window*, Event*);
103+extern void winread(Window*, uint, uint, char*);
104+extern int windel(Window*, int);
105+extern void wingetevent(Window*, Event*);
106+extern void wineventproc(void*);
107+extern void winwritebody(Window*, char*, int);
108+extern void winclean(Window*);
109+extern int winselect(Window*, char*, int);
110+extern char* winselection(Window*);
111+extern int winsetaddr(Window*, char*, int);
112+extern char* winreadbody(Window*, int*);
113+extern void windormant(Window*);
114+extern void winsetdump(Window*, char*, char*);
115+
116+extern void readmbox(Message*, char*, char*);
117+extern void rewritembox(Window*, Message*);
118+
119+extern void mkreply(Message*, char*, char*, Plumbattr*, char*);
120+extern void delreply(Message*);
121+
122+extern int mesgadd(Message*, char*, Dir*, char*);
123+extern void mesgmenu(Window*, Message*);
124+extern void mesgmenunew(Window*, Message*);
125+extern int mesgopen(Message*, char*, char*, Message*, int, char*);
126+extern void mesgctl(void*);
127+extern void mesgsend(Message*);
128+extern void mesgdel(Message*, Message*);
129+extern void mesgmenudel(Window*, Message*, Message*);
130+extern void mesgmenumark(Window*, char*, char*);
131+extern void mesgmenumarkdel(Window*, Message*, Message*, int);
132+extern Message* mesglookup(Message*, char*, char*);
133+extern Message* mesglookupfile(Message*, char*, char*);
134+extern void mesgfreeparts(Message*);
135+
136+extern char* readfile(char*, char*, int*);
137+extern char* readbody(char*, char*, int*);
138+extern void ctlprint(int, char*, ...);
139+extern void* emalloc(uint);
140+extern void* erealloc(void*, uint);
141+extern char* estrdup(char*);
142+extern char* estrstrdup(char*, char*);
143+extern char* egrow(char*, char*, char*);
144+extern char* eappend(char*, char*, char*);
145+extern void error(char*, ...);
146+extern int tokenizec(char*, char**, int, char*);
147+extern void execproc(void*);
148+
149+#pragma varargck argpos error 1
150+#pragma varargck argpos ctlprint 2
151+
152+extern Window *wbox;
153+extern Message mbox;
154+extern Message replies;
155+extern char *fsname;
156+extern int plumbsendfd;
157+extern int plumbseemailfd;
158+extern char *home;
159+extern char *outgoing;
160+extern char *mailboxdir;
161+extern char *user;
162+extern char deleted[];
163+extern int wctlfd;
164+extern int shortmenu;
acme/mail/src/html.6+0−0

Binary file not shown.

acme/mail/src/html.8+0−0

Binary file not shown.

acme/mail/src/html.c+75−0
@@ -0,0 +1,75 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include <ctype.h>
6+#include <plumb.h>
7+#include "dat.h"
8+
9+
10+char*
11+formathtml(char *body, int *np)
12+{
13+ int i, j, p[2], q[2];
14+ Exec *e;
15+ char buf[1024];
16+ Channel *sync;
17+
18+ e = emalloc(sizeof(struct Exec));
19+ if(pipe(p) < 0 || pipe(q) < 0)
20+ error("can't create pipe: %r");
21+
22+ e->p[0] = p[0];
23+ e->p[1] = p[1];
24+ e->q[0] = q[0];
25+ e->q[1] = q[1];
26+ e->argv = emalloc(3*sizeof(char*));
27+ e->argv[0] = estrdup("htmlfmt");
28+ e->argv[1] = estrdup("-cutf-8");
29+ e->argv[2] = nil;
30+ e->prog = "/bin/htmlfmt";
31+ sync = chancreate(sizeof(int), 0);
32+ e->sync = sync;
33+ proccreate(execproc, e, EXECSTACK);
34+ recvul(sync);
35+ close(p[0]);
36+ close(q[1]);
37+
38+ if((i=write(p[1], body, *np)) != *np){
39+ fprint(2, "Mail: warning: htmlfmt failed: wrote %d of %d: %r\n", i, *np);
40+ close(p[1]);
41+ close(q[0]);
42+ return body;
43+ }
44+ close(p[1]);
45+
46+ free(body);
47+ body = nil;
48+ i = 0;
49+ for(;;){
50+ j = read(q[0], buf, sizeof buf);
51+ if(j <= 0)
52+ break;
53+ body = realloc(body, i+j+1);
54+ if(body == nil)
55+ error("realloc failed: %r");
56+ memmove(body+i, buf, j);
57+ i += j;
58+ body[i] = '\0';
59+ }
60+ close(q[0]);
61+
62+ *np = i;
63+ return body;
64+}
65+
66+char*
67+readbody(char *type, char *dir, int *np)
68+{
69+ char *body;
70+
71+ body = readfile(dir, "body", np);
72+ if(body != nil && strcmp(type, "text/html") == 0)
73+ return formathtml(body, np);
74+ return body;
75+}
acme/mail/src/mail.6+0−0

Binary file not shown.

acme/mail/src/mail.8+0−0

Binary file not shown.

acme/mail/src/mail.c+550−0
@@ -0,0 +1,550 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include <plumb.h>
6+#include <ctype.h>
7+#include "dat.h"
8+
9+char *maildir = "/mail/fs/"; /* mountpoint of mail file system */
10+char *mailtermdir = "/mnt/term/mail/fs/"; /* alternate mountpoint */
11+char *mboxname = "mbox"; /* mailboxdir/mboxname is mail spool file */
12+char *mailboxdir = nil; /* nil == /mail/box/$user */
13+char *fsname; /* filesystem for mailboxdir/mboxname is at maildir/fsname */
14+char *user;
15+char *outgoing;
16+
17+Window *wbox;
18+Message mbox;
19+Message replies;
20+char *home;
21+int plumbsendfd;
22+int plumbseemailfd;
23+int plumbshowmailfd;
24+int plumbsendmailfd;
25+Channel *cplumb;
26+Channel *cplumbshow;
27+Channel *cplumbsend;
28+int wctlfd;
29+void mainctl(void*);
30+void plumbproc(void*);
31+void plumbshowproc(void*);
32+void plumbsendproc(void*);
33+void plumbthread(void);
34+void plumbshowthread(void*);
35+void plumbsendthread(void*);
36+
37+int shortmenu;
38+
39+void
40+usage(void)
41+{
42+ fprint(2, "usage: Mail [-sS] [-o outgoing] [mailboxname [directoryname]]\n");
43+ threadexitsall("usage");
44+}
45+
46+void
47+removeupasfs(void)
48+{
49+ char buf[256];
50+
51+ if(strcmp(mboxname, "mbox") == 0)
52+ return;
53+ snprint(buf, sizeof buf, "close %s", mboxname);
54+ write(mbox.ctlfd, buf, strlen(buf));
55+}
56+
57+int
58+ismaildir(char *s)
59+{
60+ char buf[256];
61+ Dir *d;
62+ int ret;
63+
64+ snprint(buf, sizeof buf, "%s%s", maildir, s);
65+ d = dirstat(buf);
66+ if(d == nil)
67+ return 0;
68+ ret = d->qid.type & QTDIR;
69+ free(d);
70+ return ret;
71+}
72+
73+void
74+threadmain(int argc, char *argv[])
75+{
76+ char *s, *name;
77+ char err[ERRMAX], *cmd;
78+ int i, newdir;
79+ Fmt fmt;
80+
81+ doquote = needsrcquote;
82+ quotefmtinstall();
83+
84+ /* open these early so we won't miss notification of new mail messages while we read mbox */
85+ plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
86+ plumbseemailfd = plumbopen("seemail", OREAD|OCEXEC);
87+ plumbshowmailfd = plumbopen("showmail", OREAD|OCEXEC);
88+
89+ shortmenu = 0;
90+ ARGBEGIN{
91+ case 's':
92+ shortmenu = 1;
93+ break;
94+ case 'S':
95+ shortmenu = 2;
96+ break;
97+ case 'o':
98+ outgoing = EARGF(usage());
99+ break;
100+ case 'm':
101+ smprint(maildir, "%s/", EARGF(usage()));
102+ break;
103+ default:
104+ usage();
105+ }ARGEND
106+
107+ name = "mbox";
108+
109+ /* bind the terminal /mail/fs directory over the local one */
110+ if(access(maildir, 0)<0 && access(mailtermdir, 0)==0)
111+ bind(mailtermdir, maildir, MAFTER);
112+
113+ newdir = 1;
114+ if(argc > 0){
115+ i = strlen(argv[0]);
116+ if(argc>2 || i==0)
117+ usage();
118+ /* see if the name is that of an existing /mail/fs directory */
119+ if(argc==1 && strchr(argv[0], '/')==0 && ismaildir(argv[0])){
120+ name = argv[0];
121+ mboxname = eappend(estrdup(maildir), "", name);
122+ newdir = 0;
123+ }else{
124+ if(argv[0][i-1] == '/')
125+ argv[0][i-1] = '\0';
126+ s = strrchr(argv[0], '/');
127+ if(s == nil)
128+ mboxname = estrdup(argv[0]);
129+ else{
130+ *s++ = '\0';
131+ if(*s == '\0')
132+ usage();
133+ mailboxdir = argv[0];
134+ mboxname = estrdup(s);
135+ }
136+ if(argc > 1)
137+ name = argv[1];
138+ else
139+ name = mboxname;
140+ }
141+ }
142+
143+ user = getenv("user");
144+ if(user == nil)
145+ user = "none";
146+ if(mailboxdir == nil)
147+ mailboxdir = estrstrdup("/mail/box/", user);
148+ if(outgoing == nil)
149+ outgoing = estrstrdup(mailboxdir, "/outgoing");
150+
151+ s = estrstrdup(maildir, "ctl");
152+ mbox.ctlfd = open(s, ORDWR|OCEXEC);
153+ if(mbox.ctlfd < 0)
154+ error("can't open %s: %r", s);
155+
156+ fsname = estrdup(name);
157+ if(newdir && argc > 0){
158+ s = emalloc(5+strlen(mailboxdir)+strlen(mboxname)+strlen(name)+10+1);
159+ for(i=0; i<10; i++){
160+ sprint(s, "open %s/%s %s", mailboxdir, mboxname, fsname);
161+ if(write(mbox.ctlfd, s, strlen(s)) >= 0)
162+ break;
163+ err[0] = '\0';
164+ errstr(err, sizeof err);
165+ if(strstr(err, "mbox name in use") == nil)
166+ error("can't create directory %s for mail: %s", name, err);
167+ free(fsname);
168+ fsname = emalloc(strlen(name)+10);
169+ sprint(fsname, "%s-%d", name, i);
170+ }
171+ if(i == 10)
172+ error("can't open %s/%s: %r", mailboxdir, mboxname);
173+ free(s);
174+ }
175+
176+ s = estrstrdup(fsname, "/");
177+ mbox.name = estrstrdup(maildir, s);
178+ mbox.level= 0;
179+ readmbox(&mbox, maildir, s);
180+ home = getenv("home");
181+ if(home == nil)
182+ home = "/";
183+
184+ wbox = newwindow();
185+ winname(wbox, mbox.name);
186+ wintagwrite(wbox, "Put Mail Delmesg ", 3+1+4+1+7+1);
187+ threadcreate(mainctl, wbox, STACK);
188+
189+ fmtstrinit(&fmt);
190+ fmtprint(&fmt, "Mail");
191+ if(shortmenu)
192+ fmtprint(&fmt, " -%c", "sS"[shortmenu-1]);
193+ if(outgoing)
194+ fmtprint(&fmt, " -o %s", outgoing);
195+ fmtprint(&fmt, " %s", name);
196+ cmd = fmtstrflush(&fmt);
197+ if(cmd == nil)
198+ sysfatal("out of memory");
199+ winsetdump(wbox, "/acme/mail", cmd);
200+ mbox.w = wbox;
201+
202+ mesgmenu(wbox, &mbox);
203+ winclean(wbox);
204+
205+ wctlfd = open("/dev/wctl", OWRITE|OCEXEC); /* for acme window */
206+ cplumb = chancreate(sizeof(Plumbmsg*), 0);
207+ cplumbshow = chancreate(sizeof(Plumbmsg*), 0);
208+ if(strcmp(name, "mbox") == 0){
209+ /*
210+ * Avoid creating multiple windows to send mail by only accepting
211+ * sendmail plumb messages if we're reading the main mailbox.
212+ */
213+ plumbsendmailfd = plumbopen("sendmail", OREAD|OCEXEC);
214+ cplumbsend = chancreate(sizeof(Plumbmsg*), 0);
215+ proccreate(plumbsendproc, nil, STACK);
216+ threadcreate(plumbsendthread, nil, STACK);
217+ }
218+ /* start plumb reader as separate proc ... */
219+ proccreate(plumbproc, nil, STACK);
220+ proccreate(plumbshowproc, nil, STACK);
221+ threadcreate(plumbshowthread, nil, STACK);
222+ /* ... and use this thread to read the messages */
223+ plumbthread();
224+}
225+
226+void
227+plumbproc(void*)
228+{
229+ Plumbmsg *m;
230+
231+ threadsetname("plumbproc");
232+ for(;;){
233+ m = plumbrecv(plumbseemailfd);
234+ sendp(cplumb, m);
235+ if(m == nil)
236+ threadexits(nil);
237+ }
238+}
239+
240+void
241+plumbshowproc(void*)
242+{
243+ Plumbmsg *m;
244+
245+ threadsetname("plumbshowproc");
246+ for(;;){
247+ m = plumbrecv(plumbshowmailfd);
248+ sendp(cplumbshow, m);
249+ if(m == nil)
250+ threadexits(nil);
251+ }
252+}
253+
254+void
255+plumbsendproc(void*)
256+{
257+ Plumbmsg *m;
258+
259+ threadsetname("plumbsendproc");
260+ for(;;){
261+ m = plumbrecv(plumbsendmailfd);
262+ sendp(cplumbsend, m);
263+ if(m == nil)
264+ threadexits(nil);
265+ }
266+}
267+
268+void
269+newmesg(char *name, char *digest)
270+{
271+ Dir *d;
272+
273+ if(strncmp(name, mbox.name, strlen(mbox.name)) != 0)
274+ return; /* message is about another mailbox */
275+ if(mesglookupfile(&mbox, name, digest) != nil)
276+ return;
277+ d = dirstat(name);
278+ if(d == nil)
279+ return;
280+ if(mesgadd(&mbox, mbox.name, d, digest))
281+ mesgmenunew(wbox, &mbox);
282+ free(d);
283+}
284+
285+void
286+showmesg(char *name, char *digest)
287+{
288+ char *n;
289+
290+ if(strncmp(name, mbox.name, strlen(mbox.name)) != 0)
291+ return; /* message is about another mailbox */
292+ n = estrdup(name+strlen(mbox.name));
293+ if(n[strlen(n)-1] != '/')
294+ n = egrow(n, "/", nil);
295+ mesgopen(&mbox, mbox.name, name+strlen(mbox.name), nil, 1, digest);
296+ free(n);
297+}
298+
299+void
300+delmesg(char *name, char *digest, int dodel)
301+{
302+ Message *m;
303+
304+ m = mesglookupfile(&mbox, name, digest);
305+ if(m != nil){
306+ mesgmenumarkdel(wbox, &mbox, m, 0);
307+ if(dodel)
308+ m->writebackdel = 1;
309+ }
310+}
311+
312+void
313+plumbthread(void)
314+{
315+ Plumbmsg *m;
316+ Plumbattr *a;
317+ char *type, *digest;
318+
319+ threadsetname("plumbthread");
320+ while((m = recvp(cplumb)) != nil){
321+ a = m->attr;
322+ digest = plumblookup(a, "digest");
323+ type = plumblookup(a, "mailtype");
324+ if(type == nil)
325+ fprint(2, "Mail: plumb message with no mailtype attribute\n");
326+ else if(strcmp(type, "new") == 0)
327+ newmesg(m->data, digest);
328+ else if(strcmp(type, "delete") == 0)
329+ delmesg(m->data, digest, 0);
330+ else
331+ fprint(2, "Mail: unknown plumb attribute %s\n", type);
332+ plumbfree(m);
333+ }
334+ threadexits(nil);
335+}
336+
337+void
338+plumbshowthread(void*)
339+{
340+ Plumbmsg *m;
341+
342+ threadsetname("plumbshowthread");
343+ while((m = recvp(cplumbshow)) != nil){
344+ showmesg(m->data, plumblookup(m->attr, "digest"));
345+ plumbfree(m);
346+ }
347+ threadexits(nil);
348+}
349+
350+void
351+plumbsendthread(void*)
352+{
353+ Plumbmsg *m;
354+
355+ threadsetname("plumbsendthread");
356+ while((m = recvp(cplumbsend)) != nil){
357+ mkreply(nil, "Mail", m->data, m->attr, nil);
358+ plumbfree(m);
359+ }
360+ threadexits(nil);
361+}
362+
363+int
364+mboxcommand(Window *w, char *s)
365+{
366+ char *args[10], **targs;
367+ Message *m, *next;
368+ int ok, nargs, i, j;
369+ char buf[128];
370+
371+ nargs = tokenize(s, args, nelem(args));
372+ if(nargs == 0)
373+ return 0;
374+ if(strcmp(args[0], "Mail") == 0){
375+ if(nargs == 1)
376+ mkreply(nil, "Mail", "", nil, nil);
377+ else
378+ mkreply(nil, "Mail", args[1], nil, nil);
379+ return 1;
380+ }
381+ if(strcmp(s, "Del") == 0){
382+ if(mbox.dirty){
383+ mbox.dirty = 0;
384+ fprint(2, "mail: mailbox not written\n");
385+ return 1;
386+ }
387+ ok = 1;
388+ for(m=mbox.head; m!=nil; m=next){
389+ next = m->next;
390+ if(m->w){
391+ if(windel(m->w, 0))
392+ m->w = nil;
393+ else
394+ ok = 0;
395+ }
396+ }
397+ for(m=replies.head; m!=nil; m=next){
398+ next = m->next;
399+ if(m->w){
400+ if(windel(m->w, 0))
401+ m->w = nil;
402+ else
403+ ok = 0;
404+ }
405+ }
406+ if(ok){
407+ windel(w, 1);
408+ removeupasfs();
409+ threadexitsall(nil);
410+ }
411+ return 1;
412+ }
413+ if(strcmp(s, "Put") == 0){
414+ rewritembox(wbox, &mbox);
415+ return 1;
416+ }
417+ if(strcmp(s, "Delmesg") == 0){
418+ if(nargs > 1){
419+ for(i=1; i<nargs; i++){
420+ snprint(buf, sizeof buf, "%s%s", mbox.name, args[i]);
421+ delmesg(buf, nil, 1);
422+ }
423+ }
424+ s = winselection(w);
425+ if(s == nil)
426+ return 1;
427+ nargs = 1;
428+ for(i=0; s[i]; i++)
429+ if(s[i] == '\n')
430+ nargs++;
431+ targs = emalloc(nargs*sizeof(char*)); /* could be too many for a local array */
432+ nargs = getfields(s, targs, nargs, 1, "\n");
433+ for(i=0; i<nargs; i++){
434+ if(!isdigit(targs[i][0]))
435+ continue;
436+ j = atoi(targs[i]); /* easy way to parse the number! */
437+ if(j == 0)
438+ continue;
439+ snprint(buf, sizeof buf, "%s%d", mbox.name, j);
440+ delmesg(buf, nil, 1);
441+ }
442+ free(s);
443+ free(targs);
444+ return 1;
445+ }
446+ return 0;
447+}
448+
449+void
450+mainctl(void *v)
451+{
452+ Window *w;
453+ Event *e, *e2, *eq, *ea;
454+ int na, nopen;
455+ char *s, *t, *buf;
456+
457+ w = v;
458+ proccreate(wineventproc, w, STACK);
459+
460+ for(;;){
461+ e = recvp(w->cevent);
462+ switch(e->c1){
463+ default:
464+ Unknown:
465+ print("unknown message %c%c\n", e->c1, e->c2);
466+ break;
467+
468+ case 'E': /* write to body; can't affect us */
469+ break;
470+
471+ case 'F': /* generated by our actions; ignore */
472+ break;
473+
474+ case 'K': /* type away; we don't care */
475+ break;
476+
477+ case 'M':
478+ switch(e->c2){
479+ case 'x':
480+ case 'X':
481+ ea = nil;
482+ e2 = nil;
483+ if(e->flag & 2)
484+ e2 = recvp(w->cevent);
485+ if(e->flag & 8){
486+ ea = recvp(w->cevent);
487+ na = ea->nb;
488+ recvp(w->cevent);
489+ }else
490+ na = 0;
491+ s = e->b;
492+ /* if it's a known command, do it */
493+ if((e->flag&2) && e->nb==0)
494+ s = e2->b;
495+ if(na){
496+ t = emalloc(strlen(s)+1+na+1);
497+ sprint(t, "%s %s", s, ea->b);
498+ s = t;
499+ }
500+ /* if it's a long message, it can't be for us anyway */
501+ if(!mboxcommand(w, s)) /* send it back */
502+ winwriteevent(w, e);
503+ if(na)
504+ free(s);
505+ break;
506+
507+ case 'l':
508+ case 'L':
509+ buf = nil;
510+ eq = e;
511+ if(e->flag & 2){
512+ e2 = recvp(w->cevent);
513+ eq = e2;
514+ }
515+ s = eq->b;
516+ if(eq->q1>eq->q0 && eq->nb==0){
517+ buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
518+ winread(w, eq->q0, eq->q1, buf);
519+ s = buf;
520+ }
521+ nopen = 0;
522+ do{
523+ /* skip 'deleted' string if present' */
524+ if(strncmp(s, deleted, strlen(deleted)) == 0)
525+ s += strlen(deleted);
526+ /* skip mail box name if present */
527+ if(strncmp(s, mbox.name, strlen(mbox.name)) == 0)
528+ s += strlen(mbox.name);
529+ nopen += mesgopen(&mbox, mbox.name, s, nil, 0, nil);
530+ while(*s!='\0' && *s++!='\n')
531+ ;
532+ }while(*s);
533+ if(nopen == 0) /* send it back */
534+ winwriteevent(w, e);
535+ free(buf);
536+ break;
537+
538+ case 'I': /* modify away; we don't care */
539+ case 'D':
540+ case 'd':
541+ case 'i':
542+ break;
543+
544+ default:
545+ goto Unknown;
546+ }
547+ }
548+ }
549+}
550+
acme/mail/src/mesg.6+0−0

Binary file not shown.

acme/mail/src/mesg.8+0−0

Binary file not shown.

acme/mail/src/mesg.c+1322−0
@@ -0,0 +1,1322 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include <ctype.h>
6+#include <plumb.h>
7+#include "dat.h"
8+
9+enum
10+{
11+ DIRCHUNK = 32*sizeof(Dir)
12+};
13+
14+char regexchars[] = "\\/[].+?()*^$";
15+char deleted[] = "(deleted)-";
16+char deletedrx[] = "\\(deleted\\)-";
17+char deletedrx01[] = "(\\(deleted\\)-)?";
18+char deletedaddr[] = "-#0;/^\\(deleted\\)-/";
19+
20+struct{
21+ char *type;
22+ char *port;
23+ char *suffix;
24+} ports[] = {
25+ "text/", "edit", ".txt",
26+ /* text must be first for plumbport() */
27+ "image/gif", "image", ".gif",
28+ "image/jpeg", "image", ".jpg",
29+ "image/jpeg", "image", ".jpeg",
30+ "image/png", "image", ".png",
31+ "image/tiff", "image", ".tif",
32+ "application/postscript", "postscript", ".ps",
33+ "application/pdf", "postscript", ".pdf",
34+ "application/msword", "msword", ".doc",
35+ "application/rtf", "msword", ".rtf",
36+ "audio/x-wav", "wav", ".wav",
37+ nil, nil
38+};
39+
40+char *goodtypes[] = {
41+ "text",
42+ "text/plain",
43+ "message/rfc822",
44+ "text/richtext",
45+ "text/tab-separated-values",
46+ "application/octet-stream",
47+ nil,
48+};
49+
50+struct{
51+ char *type;
52+ char *ext;
53+} exts[] = {
54+ "image/gif", ".gif",
55+ "image/jpeg", ".jpg",
56+ nil, nil
57+};
58+
59+char *okheaders[] =
60+{
61+ "From:",
62+ "Date:",
63+ "To:",
64+ "CC:",
65+ "Subject:",
66+ nil
67+};
68+
69+char *extraheaders[] =
70+{
71+ "Resent-From:",
72+ "Resent-To:",
73+ "Sort:",
74+ nil,
75+};
76+
77+char*
78+line(char *data, char **pp)
79+{
80+ char *p, *q;
81+
82+ for(p=data; *p!='\0' && *p!='\n'; p++)
83+ ;
84+ if(*p == '\n')
85+ *pp = p+1;
86+ else
87+ *pp = p;
88+ q = emalloc(p-data + 1);
89+ memmove(q, data, p-data);
90+ return q;
91+}
92+
93+void
94+scanheaders(Message *m, char *dir)
95+{
96+ char *s, *t, *u, *f;
97+
98+ s = f = readfile(dir, "header", nil);
99+ if(s != nil)
100+ while(*s){
101+ t = line(s, &s);
102+ if(strncmp(t, "From: ", 6) == 0){
103+ m->fromcolon = estrdup(t+6);
104+ /* remove all quotes; they're ugly and irregular */
105+ for(u=m->fromcolon; *u; u++)
106+ if(*u == '"')
107+ memmove(u, u+1, strlen(u));
108+ }
109+ if(strncmp(t, "Subject: ", 9) == 0)
110+ m->subject = estrdup(t+9);
111+ free(t);
112+ }
113+ if(m->fromcolon == nil)
114+ m->fromcolon = estrdup(m->from);
115+ free(f);
116+}
117+
118+int
119+loadinfo(Message *m, char *dir)
120+{
121+ int n;
122+ char *data, *p, *s;
123+
124+ data = readfile(dir, "info", &n);
125+ if(data == nil)
126+ return 0;
127+ m->from = line(data, &p);
128+ scanheaders(m, dir); /* depends on m->from being set */
129+ m->to = line(p, &p);
130+ m->cc = line(p, &p);
131+ m->replyto = line(p, &p);
132+ m->date = line(p, &p);
133+ s = line(p, &p);
134+ if(m->subject == nil)
135+ m->subject = s;
136+ else
137+ free(s);
138+ m->type = line(p, &p);
139+ m->disposition = line(p, &p);
140+ m->filename = line(p, &p);
141+ m->digest = line(p, &p);
142+ free(data);
143+ return 1;
144+}
145+
146+int
147+isnumeric(char *s)
148+{
149+ while(*s){
150+ if(!isdigit(*s))
151+ return 0;
152+ s++;
153+ }
154+ return 1;
155+}
156+
157+Dir*
158+loaddir(char *name, int *np)
159+{
160+ int fd;
161+ Dir *dp;
162+
163+ fd = open(name, OREAD);
164+ if(fd < 0)
165+ return nil;
166+ *np = dirreadall(fd, &dp);
167+ close(fd);
168+ return dp;
169+}
170+
171+void
172+readmbox(Message *mbox, char *dir, char *subdir)
173+{
174+ char *name;
175+ Dir *d, *dirp;
176+ int i, n;
177+
178+ name = estrstrdup(dir, subdir);
179+ dirp = loaddir(name, &n);
180+ mbox->recursed = 1;
181+ if(dirp)
182+ for(i=0; i<n; i++){
183+ d = &dirp[i];
184+ if(isnumeric(d->name))
185+ mesgadd(mbox, name, d, nil);
186+ }
187+ free(dirp);
188+ free(name);
189+}
190+
191+/* add message to box, in increasing numerical order */
192+int
193+mesgadd(Message *mbox, char *dir, Dir *d, char *digest)
194+{
195+ Message *m;
196+ char *name;
197+ int loaded;
198+
199+ m = emalloc(sizeof(Message));
200+ m->name = estrstrdup(d->name, "/");
201+ m->next = nil;
202+ m->prev = mbox->tail;
203+ m->level= mbox->level+1;
204+ m->recursed = 0;
205+ name = estrstrdup(dir, m->name);
206+ loaded = loadinfo(m, name);
207+ free(name);
208+ /* if two upas/fs are running, we can get misled, so check digest before accepting message */
209+ if(loaded==0 || (digest!=nil && m->digest!=nil && strcmp(digest, m->digest)!=0)){
210+ mesgfreeparts(m);
211+ free(m);
212+ return 0;
213+ }
214+ if(mbox->tail != nil)
215+ mbox->tail->next = m;
216+ mbox->tail = m;
217+ if(mbox->head == nil)
218+ mbox->head = m;
219+
220+ if (m->level != 1){
221+ m->recursed = 1;
222+ readmbox(m, dir, m->name);
223+ }
224+ return 1;
225+}
226+
227+int
228+thisyear(char *year)
229+{
230+ static char now[10];
231+ char *s;
232+
233+ if(now[0] == '\0'){
234+ s = ctime(time(nil));
235+ strcpy(now, s+24);
236+ }
237+ return strncmp(year, now, 4) == 0;
238+}
239+
240+char*
241+stripdate(char *as)
242+{
243+ int n;
244+ char *s, *fld[10];
245+
246+ as = estrdup(as);
247+ s = estrdup(as);
248+ n = tokenize(s, fld, 10);
249+ if(n > 5){
250+ sprint(as, "%.3s ", fld[0]); /* day */
251+ /* some dates have 19 Apr, some Apr 19 */
252+ if(strlen(fld[1])<4 && isnumeric(fld[1]))
253+ sprint(as+strlen(as), "%.3s %.3s ", fld[1], fld[2]); /* date, month */
254+ else
255+ sprint(as+strlen(as), "%.3s %.3s ", fld[2], fld[1]); /* date, month */
256+ /* do we use time or year? depends on whether year matches this one */
257+ if(thisyear(fld[5])){
258+ if(strchr(fld[3], ':') != nil)
259+ sprint(as+strlen(as), "%.5s ", fld[3]); /* time */
260+ else if(strchr(fld[4], ':') != nil)
261+ sprint(as+strlen(as), "%.5s ", fld[4]); /* time */
262+ }else
263+ sprint(as+strlen(as), "%.4s ", fld[5]); /* year */
264+ }
265+ free(s);
266+ return as;
267+}
268+
269+char*
270+readfile(char *dir, char *name, int *np)
271+{
272+ char *file, *data;
273+ int fd, len;
274+ Dir *d;
275+
276+ if(np != nil)
277+ *np = 0;
278+ file = estrstrdup(dir, name);
279+ fd = open(file, OREAD);
280+ if(fd < 0)
281+ return nil;
282+ d = dirfstat(fd);
283+ free(file);
284+ len = 0;
285+ if(d != nil)
286+ len = d->length;
287+ free(d);
288+ data = emalloc(len+1);
289+ read(fd, data, len);
290+ close(fd);
291+ if(np != nil)
292+ *np = len;
293+ return data;
294+}
295+
296+char*
297+info(Message *m, int ind, int ogf)
298+{
299+ char *i;
300+ int j, len, lens;
301+ char *p;
302+ char fmt[80], s[80];
303+
304+ if (ogf)
305+ p=m->to;
306+ else
307+ p=m->fromcolon;
308+
309+ if(ind==0 && shortmenu){
310+ len = 30;
311+ lens = 30;
312+ if(shortmenu > 1){
313+ len = 10;
314+ lens = 25;
315+ }
316+ if(ind==0 && m->subject[0]=='\0'){
317+ snprint(fmt, sizeof fmt, " %%-%d.%ds", len, len);
318+ snprint(s, sizeof s, fmt, p);
319+ }else{
320+ snprint(fmt, sizeof fmt, " %%-%d.%ds %%-%d.%ds", len, len, lens, lens);
321+ snprint(s, sizeof s, fmt, p, m->subject);
322+ }
323+ i = estrdup(s);
324+
325+ return i;
326+ }
327+
328+ i = estrdup("");
329+ i = eappend(i, "\t", p);
330+ i = egrow(i, "\t", stripdate(m->date));
331+ if(ind == 0){
332+ if(strcmp(m->type, "text")!=0 && strncmp(m->type, "text/", 5)!=0 &&
333+ strncmp(m->type, "multipart/", 10)!=0)
334+ i = egrow(i, "\t(", estrstrdup(m->type, ")"));
335+ }else if(strncmp(m->type, "multipart/", 10) != 0)
336+ i = egrow(i, "\t(", estrstrdup(m->type, ")"));
337+ if(m->subject[0] != '\0'){
338+ i = eappend(i, "\n", nil);
339+ for(j=0; j<ind; j++)
340+ i = eappend(i, "\t", nil);
341+ i = eappend(i, "\t", m->subject);
342+ }
343+ return i;
344+}
345+
346+void
347+mesgmenu0(Window *w, Message *mbox, char *realdir, char *dir, int ind, Biobuf *fd, int onlyone, int dotail)
348+{
349+ int i;
350+ Message *m;
351+ char *name, *tmp;
352+ int ogf=0;
353+
354+ if(strstr(realdir, "outgoing") != nil)
355+ ogf=1;
356+
357+ /* show mail box in reverse order, pieces in forward order */
358+ if(ind > 0)
359+ m = mbox->head;
360+ else
361+ m = mbox->tail;
362+ while(m != nil){
363+ for(i=0; i<ind; i++)
364+ Bprint(fd, "\t");
365+ if(ind != 0)
366+ Bprint(fd, " ");
367+ name = estrstrdup(dir, m->name);
368+ tmp = info(m, ind, ogf);
369+ Bprint(fd, "%s%s\n", name, tmp);
370+ free(tmp);
371+ if(dotail && m->tail)
372+ mesgmenu0(w, m, realdir, name, ind+1, fd, 0, dotail);
373+ free(name);
374+ if(ind)
375+ m = m->next;
376+ else
377+ m = m->prev;
378+ if(onlyone)
379+ m = nil;
380+ }
381+}
382+
383+void
384+mesgmenu(Window *w, Message *mbox)
385+{
386+ winopenbody(w, OWRITE);
387+ mesgmenu0(w, mbox, mbox->name, "", 0, w->body, 0, !shortmenu);
388+ winclosebody(w);
389+}
390+
391+/* one new message has arrived, as mbox->tail */
392+void
393+mesgmenunew(Window *w, Message *mbox)
394+{
395+ Biobuf *b;
396+
397+ winselect(w, "0", 0);
398+ w->data = winopenfile(w, "data");
399+ b = emalloc(sizeof(Biobuf));
400+ Binit(b, w->data, OWRITE);
401+ mesgmenu0(w, mbox, mbox->name, "", 0, b, 1, !shortmenu);
402+ Bterm(b);
403+ free(b);
404+ if(!mbox->dirty)
405+ winclean(w);
406+ /* select tag line plus following indented lines, but not final newline (it's distinctive) */
407+ winselect(w, "0/.*\\n((\t.*\\n)*\t.*)?/", 1);
408+ close(w->addr);
409+ close(w->data);
410+ w->addr = -1;
411+ w->data = -1;
412+}
413+
414+char*
415+name2regexp(char *prefix, char *s)
416+{
417+ char *buf, *p, *q;
418+
419+ buf = emalloc(strlen(prefix)+2*strlen(s)+50); /* leave room to append more */
420+ p = buf;
421+ *p++ = '0';
422+ *p++ = '/';
423+ *p++ = '^';
424+ strcpy(p, prefix);
425+ p += strlen(prefix);
426+ for(q=s; *q!='\0'; q++){
427+ if(strchr(regexchars, *q) != nil)
428+ *p++ = '\\';
429+ *p++ = *q;
430+ }
431+ *p++ = '/';
432+ *p = '\0';
433+ return buf;
434+}
435+
436+void
437+mesgmenumarkdel(Window *w, Message *mbox, Message *m, int writeback)
438+{
439+ char *buf;
440+
441+
442+ if(m->deleted)
443+ return;
444+ m->writebackdel = writeback;
445+ if(w->data < 0)
446+ w->data = winopenfile(w, "data");
447+ buf = name2regexp("", m->name);
448+ strcat(buf, "-#0");
449+ if(winselect(w, buf, 1))
450+ write(w->data, deleted, 10);
451+ free(buf);
452+ close(w->data);
453+ close(w->addr);
454+ w->addr = w->data = -1;
455+ mbox->dirty = 1;
456+ m->deleted = 1;
457+}
458+
459+void
460+mesgmenumarkundel(Window *w, Message*, Message *m)
461+{
462+ char *buf;
463+
464+ if(m->deleted == 0)
465+ return;
466+ if(w->data < 0)
467+ w->data = winopenfile(w, "data");
468+ buf = name2regexp(deletedrx, m->name);
469+ if(winselect(w, buf, 1))
470+ if(winsetaddr(w, deletedaddr, 1))
471+ write(w->data, "", 0);
472+ free(buf);
473+ close(w->data);
474+ close(w->addr);
475+ w->addr = w->data = -1;
476+ m->deleted = 0;
477+}
478+
479+void
480+mesgmenudel(Window *w, Message *mbox, Message *m)
481+{
482+ char *buf;
483+
484+ if(w->data < 0)
485+ w->data = winopenfile(w, "data");
486+ buf = name2regexp(deletedrx, m->name);
487+ if(winsetaddr(w, buf, 1) && winsetaddr(w, ".,./.*\\n(\t.*\\n)*/", 1))
488+ write(w->data, "", 0);
489+ free(buf);
490+ close(w->data);
491+ close(w->addr);
492+ w->addr = w->data = -1;
493+ mbox->dirty = 1;
494+ m->deleted = 1;
495+}
496+
497+void
498+mesgmenumark(Window *w, char *which, char *mark)
499+{
500+ char *buf;
501+
502+ if(w->data < 0)
503+ w->data = winopenfile(w, "data");
504+ buf = name2regexp(deletedrx01, which);
505+ if(winsetaddr(w, buf, 1) && winsetaddr(w, "+0-#1", 1)) /* go to end of line */
506+ write(w->data, mark, strlen(mark));
507+ free(buf);
508+ close(w->data);
509+ close(w->addr);
510+ w->addr = w->data = -1;
511+ if(!mbox.dirty)
512+ winclean(w);
513+}
514+
515+void
516+mesgfreeparts(Message *m)
517+{
518+ free(m->name);
519+ free(m->replyname);
520+ free(m->fromcolon);
521+ free(m->from);
522+ free(m->to);
523+ free(m->cc);
524+ free(m->replyto);
525+ free(m->date);
526+ free(m->subject);
527+ free(m->type);
528+ free(m->disposition);
529+ free(m->filename);
530+ free(m->digest);
531+}
532+
533+void
534+mesgdel(Message *mbox, Message *m)
535+{
536+ Message *n, *next;
537+
538+ if(m->opened)
539+ error("internal error: deleted message still open in mesgdel");
540+ /* delete subparts */
541+ for(n=m->head; n!=nil; n=next){
542+ next = n->next;
543+ mesgdel(m, n);
544+ }
545+ /* remove this message from list */
546+ if(m->next)
547+ m->next->prev = m->prev;
548+ else
549+ mbox->tail = m->prev;
550+ if(m->prev)
551+ m->prev->next = m->next;
552+ else
553+ mbox->head = m->next;
554+
555+ mesgfreeparts(m);
556+}
557+
558+int
559+mesgsave(Message *m, char *s)
560+{
561+ int ofd, n, k, ret;
562+ char *t, *raw, *unixheader, *all;
563+
564+ t = estrstrdup(mbox.name, m->name);
565+ raw = readfile(t, "raw", &n);
566+ unixheader = readfile(t, "unixheader", &k);
567+ if(raw==nil || unixheader==nil){
568+ fprint(2, "Mail: can't read %s: %r\n", t);
569+ free(t);
570+ return 0;
571+ }
572+ free(t);
573+
574+ all = emalloc(n+k+1);
575+ memmove(all, unixheader, k);
576+ memmove(all+k, raw, n);
577+ memmove(all+k+n, "\n", 1);
578+ n = k+n+1;
579+ free(unixheader);
580+ free(raw);
581+ ret = 1;
582+ s = estrdup(s);
583+ if(s[0] != '/')
584+ s = egrow(estrdup(mailboxdir), "/", s);
585+ ofd = open(s, OWRITE);
586+ if(ofd < 0){
587+ fprint(2, "Mail: can't open %s: %r\n", s);
588+ ret = 0;
589+ }else if(seek(ofd, 0LL, 2)<0 || write(ofd, all, n)!=n){
590+ fprint(2, "Mail: save failed: can't write %s: %r\n", s);
591+ ret = 0;
592+ }
593+ free(all);
594+ close(ofd);
595+ free(s);
596+ return ret;
597+}
598+
599+int
600+mesgcommand(Message *m, char *cmd)
601+{
602+ char *s;
603+ char *args[10];
604+ int ok, ret, nargs;
605+
606+ s = cmd;
607+ ret = 1;
608+ nargs = tokenize(s, args, nelem(args));
609+ if(nargs == 0)
610+ return 0;
611+ if(strcmp(args[0], "Post") == 0){
612+ mesgsend(m);
613+ goto Return;
614+ }
615+ if(strncmp(args[0], "Save", 4) == 0){
616+ if(m->isreply)
617+ goto Return;
618+ s = estrdup("\t[saved");
619+ if(nargs==1 || strcmp(args[1], "")==0){
620+ ok = mesgsave(m, "stored");
621+ }else{
622+ ok = mesgsave(m, args[1]);
623+ s = eappend(s, " ", args[1]);
624+ }
625+ if(ok){
626+ s = egrow(s, "]", nil);
627+ mesgmenumark(mbox.w, m->name, s);
628+ }
629+ free(s);
630+ goto Return;
631+ }
632+ if(strcmp(args[0], "Reply")==0){
633+ if(nargs>=2 && strcmp(args[1], "all")==0)
634+ mkreply(m, "Replyall", nil, nil, nil);
635+ else
636+ mkreply(m, "Reply", nil, nil, nil);
637+ goto Return;
638+ }
639+ if(strcmp(args[0], "Q") == 0){
640+ s = winselection(m->w); /* will be freed by mkreply */
641+ if(nargs>=3 && strcmp(args[1], "Reply")==0 && strcmp(args[2], "all")==0)
642+ mkreply(m, "QReplyall", nil, nil, s);
643+ else
644+ mkreply(m, "QReply", nil, nil, s);
645+ goto Return;
646+ }
647+ if(strcmp(args[0], "Del") == 0){
648+ if(windel(m->w, 0)){
649+ chanfree(m->w->cevent);
650+ free(m->w);
651+ m->w = nil;
652+ if(m->isreply)
653+ delreply(m);
654+ else{
655+ m->opened = 0;
656+ m->tagposted = 0;
657+ }
658+ free(cmd);
659+ threadexits(nil);
660+ }
661+ goto Return;
662+ }
663+ if(strcmp(args[0], "Delmesg") == 0){
664+ if(!m->isreply){
665+ mesgmenumarkdel(wbox, &mbox, m, 1);
666+ free(cmd); /* mesgcommand might not return */
667+ mesgcommand(m, estrdup("Del"));
668+ return 1;
669+ }
670+ goto Return;
671+ }
672+ if(strcmp(args[0], "UnDelmesg") == 0){
673+ if(!m->isreply && m->deleted)
674+ mesgmenumarkundel(wbox, &mbox, m);
675+ goto Return;
676+ }
677+// if(strcmp(args[0], "Headers") == 0){
678+// m->showheaders();
679+// return True;
680+// }
681+
682+ ret = 0;
683+
684+ Return:
685+ free(cmd);
686+ return ret;
687+}
688+
689+void
690+mesgtagpost(Message *m)
691+{
692+ if(m->tagposted)
693+ return;
694+ wintagwrite(m->w, " Post", 5);
695+ m->tagposted = 1;
696+}
697+
698+/* need to expand selection more than default word */
699+#pragma varargck argpos eval 2
700+
701+long
702+eval(Window *w, char *s, ...)
703+{
704+ char buf[64];
705+ va_list arg;
706+
707+ va_start(arg, s);
708+ vsnprint(buf, sizeof buf, s, arg);
709+ va_end(arg);
710+
711+ if(winsetaddr(w, buf, 1)==0)
712+ return -1;
713+
714+ if(pread(w->addr, buf, 24, 0) != 24)
715+ return -1;
716+ return strtol(buf, 0, 10);
717+}
718+
719+int
720+isemail(char *s)
721+{
722+ int nat;
723+
724+ nat = 0;
725+ for(; *s; s++)
726+ if(*s == '@')
727+ nat++;
728+ else if(!isalpha(*s) && !isdigit(*s) && !strchr("_.-+/", *s))
729+ return 0;
730+ return nat==1;
731+}
732+
733+char addrdelim[] = "/[ \t\\n<>()\\[\\]]/";
734+char*
735+expandaddr(Window *w, Event *e)
736+{
737+ char *s;
738+ long q0, q1;
739+
740+ if(e->q0 != e->q1) /* cannot happen */
741+ return nil;
742+
743+ q0 = eval(w, "#%d-%s", e->q0, addrdelim);
744+ if(q0 == -1) /* bad char not found */
745+ q0 = 0;
746+ else /* increment past bad char */
747+ q0++;
748+
749+ q1 = eval(w, "#%d+%s", e->q0, addrdelim);
750+ if(q1 < 0){
751+ q1 = eval(w, "$");
752+ if(q1 < 0)
753+ return nil;
754+ }
755+ if(q0 >= q1)
756+ return nil;
757+ s = emalloc((q1-q0)*UTFmax+1);
758+ winread(w, q0, q1, s);
759+ return s;
760+}
761+
762+int
763+replytoaddr(Window *w, Message *m, Event *e, char *s)
764+{
765+ int did;
766+ char *buf;
767+ Plumbmsg *pm;
768+
769+ buf = nil;
770+ did = 0;
771+ if(e->flag & 2){
772+ /* autoexpanded; use our own bigger expansion */
773+ buf = expandaddr(w, e);
774+ if(buf == nil)
775+ return 0;
776+ s = buf;
777+ }
778+ if(isemail(s)){
779+ did = 1;
780+ pm = emalloc(sizeof(Plumbmsg));
781+ pm->src = estrdup("Mail");
782+ pm->dst = estrdup("sendmail");
783+ pm->data = estrdup(s);
784+ pm->ndata = -1;
785+ if(m->subject && m->subject[0]){
786+ pm->attr = emalloc(sizeof(Plumbattr));
787+ pm->attr->name = estrdup("Subject");
788+ if(tolower(m->subject[0]) != 'r' || tolower(m->subject[1]) != 'e' || m->subject[2] != ':')
789+ pm->attr->value = estrstrdup("Re: ", m->subject);
790+ else
791+ pm->attr->value = estrdup(m->subject);
792+ pm->attr->next = nil;
793+ }
794+ if(plumbsend(plumbsendfd, pm) < 0)
795+ fprint(2, "error writing plumb message: %r\n");
796+ plumbfree(pm);
797+ }
798+ free(buf);
799+ return did;
800+}
801+
802+
803+void
804+mesgctl(void *v)
805+{
806+ Message *m;
807+ Window *w;
808+ Event *e, *eq, *e2, *ea;
809+ int na, nopen, i, j;
810+ char *os, *s, *t, *buf;
811+
812+ m = v;
813+ w = m->w;
814+ threadsetname("mesgctl");
815+ proccreate(wineventproc, w, STACK);
816+ for(;;){
817+ e = recvp(w->cevent);
818+ switch(e->c1){
819+ default:
820+ Unk:
821+ print("unknown message %c%c\n", e->c1, e->c2);
822+ break;
823+
824+ case 'E': /* write to body; can't affect us */
825+ break;
826+
827+ case 'F': /* generated by our actions; ignore */
828+ break;
829+
830+ case 'K': /* type away; we don't care */
831+ case 'M':
832+ switch(e->c2){
833+ case 'x': /* mouse only */
834+ case 'X':
835+ ea = nil;
836+ eq = e;
837+ if(e->flag & 2){
838+ e2 = recvp(w->cevent);
839+ eq = e2;
840+ }
841+ if(e->flag & 8){
842+ ea = recvp(w->cevent);
843+ recvp(w->cevent);
844+ na = ea->nb;
845+ }else
846+ na = 0;
847+ if(eq->q1>eq->q0 && eq->nb==0){
848+ s = emalloc((eq->q1-eq->q0)*UTFmax+1);
849+ winread(w, eq->q0, eq->q1, s);
850+ }else
851+ s = estrdup(eq->b);
852+ if(na){
853+ t = emalloc(strlen(s)+1+na+1);
854+ sprint(t, "%s %s", s, ea->b);
855+ free(s);
856+ s = t;
857+ }
858+ if(!mesgcommand(m, s)) /* send it back */
859+ winwriteevent(w, e);
860+ break;
861+
862+ case 'l': /* mouse only */
863+ case 'L':
864+ buf = nil;
865+ eq = e;
866+ if(e->flag & 2){
867+ e2 = recvp(w->cevent);
868+ eq = e2;
869+ }
870+ s = eq->b;
871+ if(eq->q1>eq->q0 && eq->nb==0){
872+ buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
873+ winread(w, eq->q0, eq->q1, buf);
874+ s = buf;
875+ }
876+ os = s;
877+ nopen = 0;
878+ do{
879+ /* skip mail box name if present */
880+ if(strncmp(s, mbox.name, strlen(mbox.name)) == 0)
881+ s += strlen(mbox.name);
882+ if(strstr(s, "body") != nil){
883+ /* strip any known extensions */
884+ for(i=0; exts[i].ext!=nil; i++){
885+ j = strlen(exts[i].ext);
886+ if(strlen(s)>j && strcmp(s+strlen(s)-j, exts[i].ext)==0){
887+ s[strlen(s)-j] = '\0';
888+ break;
889+ }
890+ }
891+ if(strlen(s)>5 && strcmp(s+strlen(s)-5, "/body")==0)
892+ s[strlen(s)-4] = '\0'; /* leave / in place */
893+ }
894+ nopen += mesgopen(&mbox, mbox.name, s, m, 0, nil);
895+ while(*s!=0 && *s++!='\n')
896+ ;
897+ }while(*s);
898+ if(nopen == 0 && e->c1 == 'L')
899+ nopen += replytoaddr(w, m, e, os);
900+ if(nopen == 0)
901+ winwriteevent(w, e);
902+ free(buf);
903+ break;
904+
905+ case 'I': /* modify away; we don't care */
906+ case 'D':
907+ mesgtagpost(m);
908+ /* fall through */
909+ case 'd':
910+ case 'i':
911+ break;
912+
913+ default:
914+ goto Unk;
915+ }
916+ }
917+ }
918+}
919+
920+void
921+mesgline(Message *m, char *header, char *value)
922+{
923+ if(strlen(value) > 0)
924+ Bprint(m->w->body, "%s: %s\n", header, value);
925+}
926+
927+int
928+isprintable(char *type)
929+{
930+ int i;
931+
932+ for(i=0; goodtypes[i]!=nil; i++)
933+ if(strcmp(type, goodtypes[i])==0)
934+ return 1;
935+ return 0;
936+}
937+
938+char*
939+ext(char *type)
940+{
941+ int i;
942+
943+ for(i=0; exts[i].type!=nil; i++)
944+ if(strcmp(type, exts[i].type)==0)
945+ return exts[i].ext;
946+ return "";
947+}
948+
949+void
950+mimedisplay(Message *m, char *name, char *rootdir, Window *w, int fileonly)
951+{
952+ char *dest;
953+
954+ if(strcmp(m->disposition, "file")==0 || strlen(m->filename)!=0){
955+ if(strlen(m->filename) == 0){
956+ dest = estrdup(m->name);
957+ dest[strlen(dest)-1] = '\0';
958+ }else
959+ dest = estrdup(m->filename);
960+ if(m->filename[0] != '/')
961+ dest = egrow(estrdup(home), "/", dest);
962+ Bprint(w->body, "\tcp %s%sbody%s %q\n", rootdir, name, ext(m->type), dest);
963+ free(dest);
964+ }else if(!fileonly)
965+ Bprint(w->body, "\tfile is %s%sbody%s\n", rootdir, name, ext(m->type));
966+}
967+
968+void
969+printheader(char *dir, Biobuf *b, char **okheaders)
970+{
971+ char *s;
972+ char *lines[100];
973+ int i, j, n;
974+
975+ s = readfile(dir, "header", nil);
976+ if(s == nil)
977+ return;
978+ n = getfields(s, lines, nelem(lines), 0, "\n");
979+ for(i=0; i<n; i++)
980+ for(j=0; okheaders[j]; j++)
981+ if(cistrncmp(lines[i], okheaders[j], strlen(okheaders[j])) == 0)
982+ Bprint(b, "%s\n", lines[i]);
983+ free(s);
984+}
985+
986+void
987+mesgload(Message *m, char *rootdir, char *file, Window *w)
988+{
989+ char *s, *subdir, *name, *dir;
990+ Message *mp, *thisone;
991+ int n;
992+
993+ dir = estrstrdup(rootdir, file);
994+
995+ if(strcmp(m->type, "message/rfc822") != 0){ /* suppress headers of envelopes */
996+ if(strlen(m->from) > 0){
997+ Bprint(w->body, "From: %s\n", m->from);
998+ mesgline(m, "Date", m->date);
999+ mesgline(m, "To", m->to);
1000+ mesgline(m, "CC", m->cc);
1001+ mesgline(m, "Subject", m->subject);
1002+ printheader(dir, w->body, extraheaders);
1003+ }else{
1004+ printheader(dir, w->body, okheaders);
1005+ printheader(dir, w->body, extraheaders);
1006+ }
1007+ Bprint(w->body, "\n");
1008+ }
1009+
1010+ if(m->level == 1 && m->recursed == 0){
1011+ m->recursed = 1;
1012+ readmbox(m, rootdir, m->name);
1013+ }
1014+ if(m->head == nil){ /* single part message */
1015+ if(strcmp(m->type, "text")==0 || strncmp(m->type, "text/", 5)==0){
1016+ mimedisplay(m, m->name, rootdir, w, 1);
1017+ s = readbody(m->type, dir, &n);
1018+ winwritebody(w, s, n);
1019+ free(s);
1020+ }else
1021+ mimedisplay(m, m->name, rootdir, w, 0);
1022+ }else{
1023+ /* multi-part message, either multipart/* or message/rfc822 */
1024+ thisone = nil;
1025+ if(strcmp(m->type, "multipart/alternative") == 0){
1026+ thisone = m->head; /* in case we can't find a good one */
1027+ for(mp=m->head; mp!=nil; mp=mp->next)
1028+ if(isprintable(mp->type)){
1029+ thisone = mp;
1030+ break;
1031+ }
1032+ }
1033+ for(mp=m->head; mp!=nil; mp=mp->next){
1034+ if(thisone!=nil && mp!=thisone)
1035+ continue;
1036+ subdir = estrstrdup(dir, mp->name);
1037+ name = estrstrdup(file, mp->name);
1038+ /* skip first element in name because it's already in window name */
1039+ if(mp != m->head)
1040+ Bprint(w->body, "\n===> %s (%s) [%s]\n", strchr(name, '/')+1, mp->type, mp->disposition);
1041+ if(strcmp(mp->type, "text")==0 || strncmp(mp->type, "text/", 5)==0){
1042+ mimedisplay(mp, name, rootdir, w, 1);
1043+ printheader(subdir, w->body, okheaders);
1044+ printheader(subdir, w->body, extraheaders);
1045+ winwritebody(w, "\n", 1);
1046+ s = readbody(mp->type, subdir, &n);
1047+ winwritebody(w, s, n);
1048+ free(s);
1049+ }else{
1050+ if(strncmp(mp->type, "multipart/", 10)==0 || strcmp(mp->type, "message/rfc822")==0){
1051+ mp->w = w;
1052+ mesgload(mp, rootdir, name, w);
1053+ mp->w = nil;
1054+ }else
1055+ mimedisplay(mp, name, rootdir, w, 0);
1056+ }
1057+ free(name);
1058+ free(subdir);
1059+ }
1060+ }
1061+ free(dir);
1062+}
1063+
1064+int
1065+tokenizec(char *str, char **args, int max, char *splitc)
1066+{
1067+ int na;
1068+ int intok = 0;
1069+
1070+ if(max <= 0)
1071+ return 0;
1072+ for(na=0; *str != '\0';str++){
1073+ if(strchr(splitc, *str) == nil){
1074+ if(intok)
1075+ continue;
1076+ args[na++] = str;
1077+ intok = 1;
1078+ }else{
1079+ /* it's a separator/skip character */
1080+ *str = '\0';
1081+ if(intok){
1082+ intok = 0;
1083+ if(na >= max)
1084+ break;
1085+ }
1086+ }
1087+ }
1088+ return na;
1089+}
1090+
1091+Message*
1092+mesglookup(Message *mbox, char *name, char *digest)
1093+{
1094+ int n;
1095+ Message *m;
1096+ char *t;
1097+
1098+ if(digest){
1099+ /* can find exactly */
1100+ for(m=mbox->head; m!=nil; m=m->next)
1101+ if(strcmp(digest, m->digest) == 0)
1102+ break;
1103+ return m;
1104+ }
1105+
1106+ n = strlen(name);
1107+ if(n == 0)
1108+ return nil;
1109+ if(name[n-1] == '/')
1110+ t = estrdup(name);
1111+ else
1112+ t = estrstrdup(name, "/");
1113+ for(m=mbox->head; m!=nil; m=m->next)
1114+ if(strcmp(t, m->name) == 0)
1115+ break;
1116+ free(t);
1117+ return m;
1118+}
1119+
1120+/*
1121+ * Find plumb port, knowing type is text, given file name (by extension)
1122+ */
1123+int
1124+plumbportbysuffix(char *file)
1125+{
1126+ char *suf;
1127+ int i, nsuf, nfile;
1128+
1129+ nfile = strlen(file);
1130+ for(i=0; ports[i].type!=nil; i++){
1131+ suf = ports[i].suffix;
1132+ nsuf = strlen(suf);
1133+ if(nfile > nsuf)
1134+ if(cistrncmp(file+nfile-nsuf, suf, nsuf) == 0)
1135+ return i;
1136+ }
1137+ return 0;
1138+}
1139+
1140+/*
1141+ * Find plumb port using type and file name (by extension)
1142+ */
1143+int
1144+plumbport(char *type, char *file)
1145+{
1146+ int i;
1147+
1148+ for(i=0; ports[i].type!=nil; i++)
1149+ if(strncmp(type, ports[i].type, strlen(ports[i].type)) == 0)
1150+ return i;
1151+ /* see if it's a text type */
1152+ for(i=0; goodtypes[i]!=nil; i++)
1153+ if(strncmp(type, goodtypes[i], strlen(goodtypes[i])) == 0)
1154+ return plumbportbysuffix(file);
1155+ return -1;
1156+}
1157+
1158+void
1159+plumb(Message *m, char *dir)
1160+{
1161+ int i;
1162+ char *port;
1163+ Plumbmsg *pm;
1164+
1165+ if(strlen(m->type) == 0)
1166+ return;
1167+ i = plumbport(m->type, m->filename);
1168+ if(i < 0)
1169+ fprint(2, "can't find destination for message subpart\n");
1170+ else{
1171+ port = ports[i].port;
1172+ pm = emalloc(sizeof(Plumbmsg));
1173+ pm->src = estrdup("Mail");
1174+ if(port)
1175+ pm->dst = estrdup(port);
1176+ else
1177+ pm->dst = nil;
1178+ pm->wdir = nil;
1179+ pm->type = estrdup("text");
1180+ pm->ndata = -1;
1181+ pm->data = estrstrdup(dir, "body");
1182+ pm->data = eappend(pm->data, "", ports[i].suffix);
1183+ if(plumbsend(plumbsendfd, pm) < 0)
1184+ fprint(2, "error writing plumb message: %r\n");
1185+ plumbfree(pm);
1186+ }
1187+}
1188+
1189+int
1190+mesgopen(Message *mbox, char *dir, char *s, Message *mesg, int plumbed, char *digest)
1191+{
1192+ char *t, *u, *v;
1193+ Message *m;
1194+ char *direlem[10];
1195+ int i, ndirelem, reuse;
1196+
1197+ /* find white-space-delimited first word */
1198+ for(t=s; *t!='\0' && !isspace(*t); t++)
1199+ ;
1200+ u = emalloc(t-s+1);
1201+ memmove(u, s, t-s);
1202+ /* separate it on slashes */
1203+ ndirelem = tokenizec(u, direlem, nelem(direlem), "/");
1204+ if(ndirelem <= 0){
1205+ Error:
1206+ free(u);
1207+ return 0;
1208+ }
1209+ if(plumbed){
1210+ write(wctlfd, "top", 3);
1211+ write(wctlfd, "current", 7);
1212+ }
1213+ /* open window for message */
1214+ m = mesglookup(mbox, direlem[0], digest);
1215+ if(m == nil)
1216+ goto Error;
1217+ if(mesg!=nil && m!=mesg) /* string looked like subpart but isn't part of this message */
1218+ goto Error;
1219+ if(m->opened == 0){
1220+ if(m->w == nil){
1221+ reuse = 0;
1222+ m->w = newwindow();
1223+ }else{
1224+ reuse = 1;
1225+ /* re-use existing window */
1226+ if(winsetaddr(m->w, "0,$", 1)){
1227+ if(m->w->data < 0)
1228+ m->w->data = winopenfile(m->w, "data");
1229+ write(m->w->data, "", 0);
1230+ }
1231+ }
1232+ v = estrstrdup(mbox->name, m->name);
1233+ winname(m->w, v);
1234+ free(v);
1235+ if(!reuse){
1236+ if(m->deleted)
1237+ wintagwrite(m->w, "Q Reply all UnDelmesg Save ", 2+6+4+10+5);
1238+ else
1239+ wintagwrite(m->w, "Q Reply all Delmesg Save ", 2+6+4+8+5);
1240+ }
1241+ threadcreate(mesgctl, m, STACK);
1242+ winopenbody(m->w, OWRITE);
1243+ mesgload(m, dir, m->name, m->w);
1244+ winclosebody(m->w);
1245+ winclean(m->w);
1246+ m->opened = 1;
1247+ if(ndirelem == 1){
1248+ free(u);
1249+ return 1;
1250+ }
1251+ }
1252+ if(ndirelem == 1 && plumbport(m->type, m->filename) <= 0){
1253+ /* make sure dot is visible */
1254+ ctlprint(m->w->ctl, "show\n");
1255+ return 0;
1256+ }
1257+ /* walk to subpart */
1258+ dir = estrstrdup(dir, m->name);
1259+ for(i=1; i<ndirelem; i++){
1260+ m = mesglookup(m, direlem[i], digest);
1261+ if(m == nil)
1262+ break;
1263+ dir = egrow(dir, m->name, nil);
1264+ }
1265+ if(m != nil && plumbport(m->type, m->filename) > 0)
1266+ plumb(m, dir);
1267+ free(dir);
1268+ free(u);
1269+ return 1;
1270+}
1271+
1272+void
1273+rewritembox(Window *w, Message *mbox)
1274+{
1275+ Message *m, *next;
1276+ char *deletestr, *t;
1277+ int nopen;
1278+
1279+ deletestr = estrstrdup("delete ", fsname);
1280+
1281+ nopen = 0;
1282+ for(m=mbox->head; m!=nil; m=next){
1283+ next = m->next;
1284+ if(m->deleted == 0)
1285+ continue;
1286+ if(m->opened){
1287+ nopen++;
1288+ continue;
1289+ }
1290+ if(m->writebackdel){
1291+ /* messages deleted by plumb message are not removed again */
1292+ t = estrdup(m->name);
1293+ if(strlen(t) > 0)
1294+ t[strlen(t)-1] = '\0';
1295+ deletestr = egrow(deletestr, " ", t);
1296+ }
1297+ mesgmenudel(w, mbox, m);
1298+ mesgdel(mbox, m);
1299+ }
1300+ if(write(mbox->ctlfd, deletestr, strlen(deletestr)) < 0)
1301+ fprint(2, "Mail: warning: error removing mail message files: %r\n");
1302+ free(deletestr);
1303+ winselect(w, "0", 0);
1304+ if(nopen == 0)
1305+ winclean(w);
1306+ mbox->dirty = 0;
1307+}
1308+
1309+/* name is a full file name, but it might not belong to us */
1310+Message*
1311+mesglookupfile(Message *mbox, char *name, char *digest)
1312+{
1313+ int k, n;
1314+
1315+ k = strlen(name);
1316+ n = strlen(mbox->name);
1317+ if(k==0 || strncmp(name, mbox->name, n) != 0){
1318+// fprint(2, "Mail: message %s not in this mailbox\n", name);
1319+ return nil;
1320+ }
1321+ return mesglookup(mbox, name+n, digest);
1322+}
acme/mail/src/mkfile+30−0
@@ -0,0 +1,30 @@
1+</$objtype/mkfile
2+
3+TARG=Mail
4+OFILES=\
5+ html.$O\
6+ mail.$O\
7+ mesg.$O\
8+ reply.$O\
9+ util.$O\
10+ win.$O
11+
12+HFILES=dat.h
13+LIB=
14+
15+BIN=/acme/bin/$objtype
16+
17+UPDATE=\
18+ mkfile\
19+ $HFILES\
20+ ${OFILES:%.$O=%.c}\
21+
22+</sys/src/cmd/mkone
23+
24+$O.out: $OFILES
25+ $LD -o $target $LDFLAGS $OFILES
26+
27+syms:V:
28+ 8c -a mail.c >syms
29+ 8c -aa mesg.c reply.c util.c win.c >>syms
30+
acme/mail/src/reply.6+0−0

Binary file not shown.

acme/mail/src/reply.8+0−0

Binary file not shown.

acme/mail/src/reply.c+567−0
@@ -0,0 +1,567 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include <ctype.h>
6+#include <plumb.h>
7+#include "dat.h"
8+
9+static int replyid;
10+
11+int
12+quote(Message *m, Biobuf *b, char *dir, char *quotetext)
13+{
14+ char *body, *type;
15+ int i, n, nlines;
16+ char **lines;
17+
18+ if(quotetext){
19+ body = quotetext;
20+ n = strlen(body);
21+ type = nil;
22+ }else{
23+ /* look for first textual component to quote */
24+ type = readfile(dir, "type", &n);
25+ if(type == nil){
26+ print("no type in %s\n", dir);
27+ return 0;
28+ }
29+ if(strncmp(type, "multipart/", 10)==0 || strncmp(type, "message/", 8)==0){
30+ dir = estrstrdup(dir, "1/");
31+ if(quote(m, b, dir, nil)){
32+ free(type);
33+ free(dir);
34+ return 1;
35+ }
36+ free(dir);
37+ }
38+ if(strncmp(type, "text", 4) != 0){
39+ free(type);
40+ return 0;
41+ }
42+ body = readbody(m->type, dir, &n);
43+ if(body == nil)
44+ return 0;
45+ }
46+ nlines = 0;
47+ for(i=0; i<n; i++)
48+ if(body[i] == '\n')
49+ nlines++;
50+ nlines++;
51+ lines = emalloc(nlines*sizeof(char*));
52+ nlines = getfields(body, lines, nlines, 0, "\n");
53+ /* delete leading and trailing blank lines */
54+ i = 0;
55+ while(i<nlines && lines[i][0]=='\0')
56+ i++;
57+ while(i<nlines && lines[nlines-1][0]=='\0')
58+ nlines--;
59+ while(i < nlines){
60+ Bprint(b, ">%s%s\n", lines[i][0]=='>'? "" : " ", lines[i]);
61+ i++;
62+ }
63+ free(lines);
64+ free(body); /* will free quotetext if non-nil */
65+ free(type);
66+ return 1;
67+}
68+
69+void
70+mkreply(Message *m, char *label, char *to, Plumbattr *attr, char *quotetext)
71+{
72+ Message *r;
73+ char *dir, *t;
74+ int quotereply;
75+ Plumbattr *a;
76+
77+ quotereply = (label[0] == 'Q');
78+ r = emalloc(sizeof(Message));
79+ r->isreply = 1;
80+ if(m != nil)
81+ r->replyname = estrdup(m->name);
82+ r->next = replies.head;
83+ r->prev = nil;
84+ if(replies.head != nil)
85+ replies.head->prev = r;
86+ replies.head = r;
87+ if(replies.tail == nil)
88+ replies.tail = r;
89+ r->name = emalloc(strlen(mbox.name)+strlen(label)+10);
90+ sprint(r->name, "%s%s%d", mbox.name, label, ++replyid);
91+ r->w = newwindow();
92+ winname(r->w, r->name);
93+ ctlprint(r->w->ctl, "cleartag");
94+ wintagwrite(r->w, "fmt Look Post Undo", 4+5+5+4);
95+ r->tagposted = 1;
96+ threadcreate(mesgctl, r, STACK);
97+ winopenbody(r->w, OWRITE);
98+ if(to!=nil && to[0]!='\0')
99+ Bprint(r->w->body, "%s\n", to);
100+ for(a=attr; a; a=a->next)
101+ Bprint(r->w->body, "%s: %s\n", a->name, a->value);
102+ dir = nil;
103+ if(m != nil){
104+ dir = estrstrdup(mbox.name, m->name);
105+ if(to == nil && attr == nil){
106+ /* Reply goes to replyto; Reply all goes to From and To and CC */
107+ if(strstr(label, "all") == nil)
108+ Bprint(r->w->body, "To: %s\n", m->replyto);
109+ else{ /* Replyall */
110+ if(strlen(m->from) > 0)
111+ Bprint(r->w->body, "To: %s\n", m->from);
112+ if(strlen(m->to) > 0)
113+ Bprint(r->w->body, "To: %s\n", m->to);
114+ if(strlen(m->cc) > 0)
115+ Bprint(r->w->body, "CC: %s\n", m->cc);
116+ }
117+ }
118+ if(strlen(m->subject) > 0){
119+ t = "Subject: Re: ";
120+ if(strlen(m->subject) >= 3)
121+ if(tolower(m->subject[0])=='r' && tolower(m->subject[1])=='e' && m->subject[2]==':')
122+ t = "Subject: ";
123+ Bprint(r->w->body, "%s%s\n", t, m->subject);
124+ }
125+ if(!quotereply){
126+ Bprint(r->w->body, "Include: %sraw\n", dir);
127+ free(dir);
128+ }
129+ }
130+ Bprint(r->w->body, "\n");
131+ if(m == nil)
132+ Bprint(r->w->body, "\n");
133+ else if(quotereply){
134+ quote(m, r->w->body, dir, quotetext);
135+ free(dir);
136+ }
137+ winclosebody(r->w);
138+ if(m==nil && (to==nil || to[0]=='\0'))
139+ winselect(r->w, "0", 0);
140+ else
141+ winselect(r->w, "$", 0);
142+ winclean(r->w);
143+ windormant(r->w);
144+}
145+
146+void
147+delreply(Message *m)
148+{
149+ if(m->next == nil)
150+ replies.tail = m->prev;
151+ else
152+ m->next->prev = m->prev;
153+ if(m->prev == nil)
154+ replies.head = m->next;
155+ else
156+ m->prev->next = m->next;
157+ mesgfreeparts(m);
158+ free(m);
159+}
160+
161+/* copy argv to stack and free the incoming strings, so we don't leak argument vectors */
162+void
163+buildargv(char **inargv, char *argv[NARGS+1], char args[NARGCHAR])
164+{
165+ int i, n;
166+ char *s, *a;
167+
168+ s = args;
169+ for(i=0; i<NARGS; i++){
170+ a = inargv[i];
171+ if(a == nil)
172+ break;
173+ n = strlen(a)+1;
174+ if((s-args)+n >= NARGCHAR) /* too many characters */
175+ break;
176+ argv[i] = s;
177+ memmove(s, a, n);
178+ s += n;
179+ free(a);
180+ }
181+ argv[i] = nil;
182+}
183+
184+void
185+execproc(void *v)
186+{
187+ struct Exec *e;
188+ int p[2], q[2];
189+ char *prog;
190+ char *argv[NARGS+1], args[NARGCHAR];
191+
192+ e = v;
193+ p[0] = e->p[0];
194+ p[1] = e->p[1];
195+ q[0] = e->q[0];
196+ q[1] = e->q[1];
197+ prog = e->prog; /* known not to be malloc'ed */
198+ rfork(RFFDG);
199+ sendul(e->sync, 1);
200+ buildargv(e->argv, argv, args);
201+ free(e->argv);
202+ chanfree(e->sync);
203+ free(e);
204+ dup(p[0], 0);
205+ close(p[0]);
206+ close(p[1]);
207+ if(q[0]){
208+ dup(q[1], 1);
209+ close(q[0]);
210+ close(q[1]);
211+ }
212+ procexec(nil, prog, argv);
213+//fprint(2, "exec: %s", e->prog);
214+//{int i;
215+//for(i=0; argv[i]; i++) print(" '%s'", argv[i]);
216+//print("\n");
217+//}
218+//argv[0] = "cat";
219+//argv[1] = nil;
220+//procexec(nil, "/bin/cat", argv);
221+ fprint(2, "Mail: can't exec %s: %r\n", prog);
222+ threadexits("can't exec");
223+}
224+
225+enum{
226+ ATTACH,
227+ BCC,
228+ CC,
229+ FROM,
230+ INCLUDE,
231+ TO,
232+};
233+
234+char *headers[] = {
235+ "attach:",
236+ "bcc:",
237+ "cc:",
238+ "from:",
239+ "include:",
240+ "to:",
241+ nil,
242+};
243+
244+int
245+whichheader(char *h)
246+{
247+ int i;
248+
249+ for(i=0; headers[i]!=nil; i++)
250+ if(cistrcmp(h, headers[i]) == 0)
251+ return i;
252+ return -1;
253+}
254+
255+char *tolist[200];
256+char *cclist[200];
257+char *bcclist[200];
258+int ncc, nbcc, nto;
259+char *attlist[200];
260+char included[200];
261+
262+int
263+addressed(char *name)
264+{
265+ int i;
266+
267+ for(i=0; i<nto; i++)
268+ if(strcmp(name, tolist[i]) == 0)
269+ return 1;
270+ for(i=0; i<ncc; i++)
271+ if(strcmp(name, cclist[i]) == 0)
272+ return 1;
273+ for(i=0; i<nbcc; i++)
274+ if(strcmp(name, bcclist[i]) == 0)
275+ return 1;
276+ return 0;
277+}
278+
279+char*
280+skipbl(char *s, char *e)
281+{
282+ while(s < e){
283+ if(*s!=' ' && *s!='\t' && *s!=',')
284+ break;
285+ s++;
286+ }
287+ return s;
288+}
289+
290+char*
291+findbl(char *s, char *e)
292+{
293+ while(s < e){
294+ if(*s==' ' || *s=='\t' || *s==',')
295+ break;
296+ s++;
297+ }
298+ return s;
299+}
300+
301+/*
302+ * comma-separate possibly blank-separated strings in line; e points before newline
303+ */
304+void
305+commas(char *s, char *e)
306+{
307+ char *t;
308+
309+ /* may have initial blanks */
310+ s = skipbl(s, e);
311+ while(s < e){
312+ s = findbl(s, e);
313+ if(s == e)
314+ break;
315+ t = skipbl(s, e);
316+ if(t == e) /* no more words */
317+ break;
318+ /* patch comma */
319+ *s++ = ',';
320+ while(s < t)
321+ *s++ = ' ';
322+ }
323+}
324+
325+int
326+print2(int fd, int ofd, char *fmt, ...)
327+{
328+ int m, n;
329+ char *s;
330+ va_list arg;
331+
332+ va_start(arg, fmt);
333+ s = vsmprint(fmt, arg);
334+ va_end(arg);
335+ if(s == nil)
336+ return -1;
337+ m = strlen(s);
338+ n = write(fd, s, m);
339+ if(ofd > 0)
340+ write(ofd, s, m);
341+ return n;
342+}
343+
344+void
345+write2(int fd, int ofd, char *buf, int n, int nofrom)
346+{
347+ char *from, *p;
348+ int m;
349+
350+ write(fd, buf, n);
351+
352+ if(ofd <= 0)
353+ return;
354+
355+ if(nofrom == 0){
356+ write(ofd, buf, n);
357+ return;
358+ }
359+
360+ /* need to escape leading From lines to avoid corrupting 'outgoing' mailbox */
361+ for(p=buf; *p; p+=m){
362+ from = cistrstr(p, "from");
363+ if(from == nil)
364+ m = n;
365+ else
366+ m = from - p;
367+ if(m > 0)
368+ write(ofd, p, m);
369+ if(from){
370+ if(p==buf || from[-1]=='\n')
371+ write(ofd, " ", 1); /* escape with space if From is at start of line */
372+ write(ofd, from, 4);
373+ m += 4;
374+ }
375+ n -= m;
376+ }
377+}
378+
379+void
380+mesgsend(Message *m)
381+{
382+ char *s, *body, *to;
383+ int i, j, h, n, natt, p[2];
384+ struct Exec *e;
385+ Channel *sync;
386+ int first, nfld, delit, ofd;
387+ char *copy, *fld[100], *now;
388+
389+ body = winreadbody(m->w, &n);
390+ /* assemble to: list from first line, to: line, and cc: line */
391+ nto = 0;
392+ natt = 0;
393+ ncc = 0;
394+ nbcc = 0;
395+ first = 1;
396+ to = body;
397+ for(;;){
398+ for(s=to; *s!='\n'; s++)
399+ if(*s == '\0'){
400+ free(body);
401+ return;
402+ }
403+ if(s++ == to) /* blank line */
404+ break;
405+ /* make copy of line to tokenize */
406+ copy = emalloc(s-to);
407+ memmove(copy, to, s-to);
408+ copy[s-to-1] = '\0';
409+ nfld = tokenizec(copy, fld, nelem(fld), ", \t");
410+ if(nfld == 0){
411+ free(copy);
412+ break;
413+ }
414+ n -= s-to;
415+ switch(h = whichheader(fld[0])){
416+ case TO:
417+ case FROM:
418+ delit = 1;
419+ commas(to+strlen(fld[0]), s-1);
420+ for(i=1; i<nfld && nto<nelem(tolist); i++)
421+ if(!addressed(fld[i]))
422+ tolist[nto++] = estrdup(fld[i]);
423+ break;
424+ case BCC:
425+ delit = 1;
426+ commas(to+strlen(fld[0]), s-1);
427+ for(i=1; i<nfld && nbcc<nelem(bcclist); i++)
428+ if(!addressed(fld[i]))
429+ bcclist[nbcc++] = estrdup(fld[i]);
430+ break;
431+ case CC:
432+ delit = 1;
433+ commas(to+strlen(fld[0]), s-1);
434+ for(i=1; i<nfld && ncc<nelem(cclist); i++)
435+ if(!addressed(fld[i]))
436+ cclist[ncc++] = estrdup(fld[i]);
437+ break;
438+ case ATTACH:
439+ case INCLUDE:
440+ delit = 1;
441+ for(i=1; i<nfld && natt<nelem(attlist); i++){
442+ attlist[natt] = estrdup(fld[i]);
443+ included[natt++] = (h == INCLUDE);
444+ }
445+ break;
446+ default:
447+ if(first){
448+ delit = 1;
449+ for(i=0; i<nfld && nto<nelem(tolist); i++)
450+ tolist[nto++] = estrdup(fld[i]);
451+ }else /* ignore it */
452+ delit = 0;
453+ break;
454+ }
455+ if(delit){
456+ /* delete line from body */
457+ memmove(to, s, n+1);
458+ }else
459+ to = s;
460+ free(copy);
461+ first = 0;
462+ }
463+
464+ ofd = open(outgoing, OWRITE|OCEXEC); /* no error check necessary */
465+ if(ofd > 0){
466+ /* From dhog Fri Aug 24 22:13:00 EDT 2001 */
467+ now = ctime(time(0));
468+ fprint(ofd, "From %s %s", user, now);
469+ fprint(ofd, "From: %s\n", user);
470+ fprint(ofd, "Date: %s", now);
471+ for(i=0; i<natt; i++)
472+ if(included[i])
473+ fprint(ofd, "Include: %s\n", attlist[i]);
474+ else
475+ fprint(ofd, "Attach: %s\n", attlist[i]);
476+ /* needed because mail is by default Latin-1 */
477+ fprint(ofd, "Content-Type: text/plain; charset=\"UTF-8\"\n");
478+ fprint(ofd, "Content-Transfer-Encoding: 8bit\n");
479+ }
480+
481+ e = emalloc(sizeof(struct Exec));
482+ if(pipe(p) < 0)
483+ error("can't create pipe: %r");
484+ e->p[0] = p[0];
485+ e->p[1] = p[1];
486+ e->prog = "/bin/upas/marshal";
487+ e->argv = emalloc((1+1+2+4*natt+1)*sizeof(char*));
488+ e->argv[0] = estrdup("marshal");
489+ e->argv[1] = estrdup("-8");
490+ j = 2;
491+ if(m->replyname){
492+ e->argv[j++] = estrdup("-R");
493+ e->argv[j++] = estrstrdup(mbox.name, m->replyname);
494+ }
495+ for(i=0; i<natt; i++){
496+ if(included[i])
497+ e->argv[j++] = estrdup("-A");
498+ else
499+ e->argv[j++] = estrdup("-a");
500+ e->argv[j++] = estrdup(attlist[i]);
501+ }
502+ sync = chancreate(sizeof(int), 0);
503+ e->sync = sync;
504+ proccreate(execproc, e, EXECSTACK);
505+ recvul(sync);
506+ close(p[0]);
507+
508+ /* using marshal -8, so generate rfc822 headers */
509+ if(nto > 0){
510+ print2(p[1], ofd, "To: ");
511+ for(i=0; i<nto-1; i++)
512+ print2(p[1], ofd, "%s, ", tolist[i]);
513+ print2(p[1], ofd, "%s\n", tolist[i]);
514+ }
515+ if(ncc > 0){
516+ print2(p[1], ofd, "CC: ");
517+ for(i=0; i<ncc-1; i++)
518+ print2(p[1], ofd, "%s, ", cclist[i]);
519+ print2(p[1], ofd, "%s\n", cclist[i]);
520+ }
521+ if(nbcc > 0){
522+ print2(p[1], ofd, "BCC: ");
523+ for(i=0; i<nbcc-1; i++)
524+ print2(p[1], ofd, "%s, ", bcclist[i]);
525+ print2(p[1], ofd, "%s\n", bcclist[i]);
526+ }
527+
528+ i = strlen(body);
529+ if(i > 0)
530+ write2(p[1], ofd, body, i, 1);
531+
532+ /* guarantee a blank line, to ensure attachments are separated from body */
533+ if(i==0 || body[i-1]!='\n')
534+ write2(p[1], ofd, "\n\n", 2, 0);
535+ else if(i>1 && body[i-2]!='\n')
536+ write2(p[1], ofd, "\n", 1, 0);
537+
538+ /* these look like pseudo-attachments in the "outgoing" box */
539+ if(ofd>0 && natt>0){
540+ for(i=0; i<natt; i++)
541+ if(included[i])
542+ fprint(ofd, "=====> Include: %s\n", attlist[i]);
543+ else
544+ fprint(ofd, "=====> Attach: %s\n", attlist[i]);
545+ }
546+ if(ofd > 0)
547+ write(ofd, "\n", 1);
548+
549+ for(i=0; i<natt; i++)
550+ free(attlist[i]);
551+ close(ofd);
552+ close(p[1]);
553+ free(body);
554+
555+ if(m->replyname != nil)
556+ mesgmenumark(mbox.w, m->replyname, "\t[replied]");
557+ if(m->name[0] == '/')
558+ s = estrdup(m->name);
559+ else
560+ s = estrstrdup(mbox.name, m->name);
561+ s = egrow(s, "-R", nil);
562+ winname(m->w, s);
563+ free(s);
564+ winclean(m->w);
565+ /* mark message unopened because it's no longer the original message */
566+ m->opened = 0;
567+}
acme/mail/src/util.6+0−0

Binary file not shown.

acme/mail/src/util.8+0−0

Binary file not shown.

acme/mail/src/util.c+105−0
@@ -0,0 +1,105 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include <plumb.h>
6+#include "dat.h"
7+
8+void*
9+emalloc(uint n)
10+{
11+ void *p;
12+
13+ p = malloc(n);
14+ if(p == nil)
15+ error("can't malloc: %r");
16+ memset(p, 0, n);
17+ setmalloctag(p, getcallerpc(&n));
18+ return p;
19+}
20+
21+void*
22+erealloc(void *p, uint n)
23+{
24+ p = realloc(p, n);
25+ if(p == nil)
26+ error("can't realloc: %r");
27+ setmalloctag(p, getcallerpc(&n));
28+ return p;
29+}
30+
31+char*
32+estrdup(char *s)
33+{
34+ char *t;
35+
36+ t = emalloc(strlen(s)+1);
37+ strcpy(t, s);
38+ return t;
39+}
40+
41+char*
42+estrstrdup(char *s, char *t)
43+{
44+ char *u;
45+
46+ u = emalloc(strlen(s)+strlen(t)+1);
47+ strcpy(u, s);
48+ strcat(u, t);
49+ return u;
50+}
51+
52+char*
53+eappend(char *s, char *sep, char *t)
54+{
55+ char *u;
56+
57+ if(t == nil)
58+ u = estrstrdup(s, sep);
59+ else{
60+ u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1);
61+ strcpy(u, s);
62+ strcat(u, sep);
63+ strcat(u, t);
64+ }
65+ free(s);
66+ return u;
67+}
68+
69+char*
70+egrow(char *s, char *sep, char *t)
71+{
72+ s = eappend(s, sep, t);
73+ free(t);
74+ return s;
75+}
76+
77+void
78+error(char *fmt, ...)
79+{
80+ Fmt f;
81+ char buf[64];
82+ va_list arg;
83+
84+ fmtfdinit(&f, 2, buf, sizeof buf);
85+ fmtprint(&f, "Mail: ");
86+ va_start(arg, fmt);
87+ fmtvprint(&f, fmt, arg);
88+ va_end(arg);
89+ fmtprint(&f, "\n");
90+ fmtfdflush(&f);
91+ threadexitsall(buf);
92+}
93+
94+void
95+ctlprint(int fd, char *fmt, ...)
96+{
97+ int n;
98+ va_list arg;
99+
100+ va_start(arg, fmt);
101+ n = vfprint(fd, fmt, arg);
102+ va_end(arg);
103+ if(n <= 0)
104+ error("control file write error: %r");
105+}
acme/mail/src/win.6+0−0

Binary file not shown.

acme/mail/src/win.8+0−0

Binary file not shown.

acme/mail/src/win.c+341−0
@@ -0,0 +1,341 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include <plumb.h>
6+#include "dat.h"
7+
8+Window*
9+newwindow(void)
10+{
11+ char buf[12];
12+ Window *w;
13+
14+ w = emalloc(sizeof(Window));
15+ w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC);
16+ if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
17+ error("can't open window ctl file: %r");
18+ ctlprint(w->ctl, "noscroll\n");
19+ w->id = atoi(buf);
20+ w->event = winopenfile(w, "event");
21+ w->addr = -1; /* will be opened when needed */
22+ w->body = nil;
23+ w->data = -1;
24+ w->cevent = chancreate(sizeof(Event*), 0);
25+ return w;
26+}
27+
28+void
29+winsetdump(Window *w, char *dir, char *cmd)
30+{
31+ if(dir != nil)
32+ ctlprint(w->ctl, "dumpdir %s\n", dir);
33+ if(cmd != nil)
34+ ctlprint(w->ctl, "dump %s\n", cmd);
35+}
36+
37+void
38+wineventproc(void *v)
39+{
40+ Window *w;
41+ int i;
42+
43+ w = v;
44+ for(i=0; ; i++){
45+ if(i >= NEVENT)
46+ i = 0;
47+ wingetevent(w, &w->e[i]);
48+ sendp(w->cevent, &w->e[i]);
49+ }
50+}
51+
52+static int
53+winopenfile1(Window *w, char *f, int m)
54+{
55+ char buf[64];
56+ int fd;
57+
58+ sprint(buf, "/mnt/wsys/%d/%s", w->id, f);
59+ fd = open(buf, m|OCEXEC);
60+ if(fd < 0)
61+ error("can't open window file %s: %r", f);
62+ return fd;
63+}
64+
65+int
66+winopenfile(Window *w, char *f)
67+{
68+ return winopenfile1(w, f, ORDWR);
69+}
70+
71+void
72+wintagwrite(Window *w, char *s, int n)
73+{
74+ int fd;
75+
76+ fd = winopenfile(w, "tag");
77+ if(write(fd, s, n) != n)
78+ error("tag write: %r");
79+ close(fd);
80+}
81+
82+void
83+winname(Window *w, char *s)
84+{
85+ ctlprint(w->ctl, "name %s\n", s);
86+}
87+
88+void
89+winopenbody(Window *w, int mode)
90+{
91+ char buf[256];
92+
93+ sprint(buf, "/mnt/wsys/%d/body", w->id);
94+ w->body = Bopen(buf, mode|OCEXEC);
95+ if(w->body == nil)
96+ error("can't open window body file: %r");
97+}
98+
99+void
100+winclosebody(Window *w)
101+{
102+ if(w->body != nil){
103+ Bterm(w->body);
104+ w->body = nil;
105+ }
106+}
107+
108+void
109+winwritebody(Window *w, char *s, int n)
110+{
111+ if(w->body == nil)
112+ winopenbody(w, OWRITE);
113+ if(Bwrite(w->body, s, n) != n)
114+ error("write error to window: %r");
115+}
116+
117+int
118+wingetec(Window *w)
119+{
120+ if(w->nbuf == 0){
121+ w->nbuf = read(w->event, w->buf, sizeof w->buf);
122+ if(w->nbuf <= 0){
123+ /* probably because window has exited, and only called by wineventproc, so just shut down */
124+ threadexits(nil);
125+ }
126+ w->bufp = w->buf;
127+ }
128+ w->nbuf--;
129+ return *w->bufp++;
130+}
131+
132+int
133+wingeten(Window *w)
134+{
135+ int n, c;
136+
137+ n = 0;
138+ while('0'<=(c=wingetec(w)) && c<='9')
139+ n = n*10+(c-'0');
140+ if(c != ' ')
141+ error("event number syntax");
142+ return n;
143+}
144+
145+int
146+wingeter(Window *w, char *buf, int *nb)
147+{
148+ Rune r;
149+ int n;
150+
151+ r = wingetec(w);
152+ buf[0] = r;
153+ n = 1;
154+ if(r >= Runeself) {
155+ while(!fullrune(buf, n))
156+ buf[n++] = wingetec(w);
157+ chartorune(&r, buf);
158+ }
159+ *nb = n;
160+ return r;
161+}
162+
163+void
164+wingetevent(Window *w, Event *e)
165+{
166+ int i, nb;
167+
168+ e->c1 = wingetec(w);
169+ e->c2 = wingetec(w);
170+ e->q0 = wingeten(w);
171+ e->q1 = wingeten(w);
172+ e->flag = wingeten(w);
173+ e->nr = wingeten(w);
174+ if(e->nr > EVENTSIZE)
175+ error("event string too long");
176+ e->nb = 0;
177+ for(i=0; i<e->nr; i++){
178+ e->r[i] = wingeter(w, e->b+e->nb, &nb);
179+ e->nb += nb;
180+ }
181+ e->r[e->nr] = 0;
182+ e->b[e->nb] = 0;
183+ if(wingetec(w) != '\n')
184+ error("event syntax error");
185+}
186+
187+void
188+winwriteevent(Window *w, Event *e)
189+{
190+ fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
191+}
192+
193+void
194+winread(Window *w, uint q0, uint q1, char *data)
195+{
196+ int m, n, nr;
197+ char buf[256];
198+
199+ if(w->addr < 0)
200+ w->addr = winopenfile(w, "addr");
201+ if(w->data < 0)
202+ w->data = winopenfile(w, "data");
203+ m = q0;
204+ while(m < q1){
205+ n = sprint(buf, "#%d", m);
206+ if(write(w->addr, buf, n) != n)
207+ error("error writing addr: %r");
208+ n = read(w->data, buf, sizeof buf);
209+ if(n <= 0)
210+ error("reading data: %r");
211+ nr = utfnlen(buf, n);
212+ while(m+nr >q1){
213+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
214+ --nr;
215+ }
216+ if(n == 0)
217+ break;
218+ memmove(data, buf, n);
219+ data += n;
220+ *data = 0;
221+ m += nr;
222+ }
223+}
224+
225+void
226+windormant(Window *w)
227+{
228+ if(w->addr >= 0){
229+ close(w->addr);
230+ w->addr = -1;
231+ }
232+ if(w->body != nil){
233+ Bterm(w->body);
234+ w->body = nil;
235+ }
236+ if(w->data >= 0){
237+ close(w->data);
238+ w->data = -1;
239+ }
240+}
241+
242+
243+int
244+windel(Window *w, int sure)
245+{
246+ if(sure)
247+ write(w->ctl, "delete\n", 7);
248+ else if(write(w->ctl, "del\n", 4) != 4)
249+ return 0;
250+ /* event proc will die due to read error from event file */
251+ windormant(w);
252+ close(w->ctl);
253+ w->ctl = -1;
254+ close(w->event);
255+ w->event = -1;
256+ return 1;
257+}
258+
259+void
260+winclean(Window *w)
261+{
262+ if(w->body)
263+ Bflush(w->body);
264+ ctlprint(w->ctl, "clean\n");
265+}
266+
267+int
268+winsetaddr(Window *w, char *addr, int errok)
269+{
270+ if(w->addr < 0)
271+ w->addr = winopenfile(w, "addr");
272+ if(write(w->addr, addr, strlen(addr)) < 0){
273+ if(!errok)
274+ error("error writing addr(%s): %r", addr);
275+ return 0;
276+ }
277+ return 1;
278+}
279+
280+int
281+winselect(Window *w, char *addr, int errok)
282+{
283+ if(winsetaddr(w, addr, errok)){
284+ ctlprint(w->ctl, "dot=addr\n");
285+ return 1;
286+ }
287+ return 0;
288+}
289+
290+char*
291+winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */
292+{
293+ char *s;
294+ int m, na, n;
295+
296+ if(w->body != nil)
297+ winclosebody(w);
298+ winopenbody(w, OREAD);
299+ s = nil;
300+ na = 0;
301+ n = 0;
302+ for(;;){
303+ if(na < n+512){
304+ na += 1024;
305+ s = realloc(s, na+1);
306+ }
307+ m = Bread(w->body, s+n, na-n);
308+ if(m <= 0)
309+ break;
310+ n += m;
311+ }
312+ s[n] = 0;
313+ winclosebody(w);
314+ *np = n;
315+ return s;
316+}
317+
318+char*
319+winselection(Window *w)
320+{
321+ int fd, m, n;
322+ char *buf;
323+ char tmp[256];
324+
325+ fd = winopenfile1(w, "rdsel", OREAD);
326+ if(fd < 0)
327+ error("can't open rdsel: %r");
328+ n = 0;
329+ buf = nil;
330+ for(;;){
331+ m = read(fd, tmp, sizeof tmp);
332+ if(m <= 0)
333+ break;
334+ buf = erealloc(buf, n+m+1);
335+ memmove(buf+n, tmp, m);
336+ n += m;
337+ buf[n] = '\0';
338+ }
339+ close(fd);
340+ return buf;
341+}
acme/mkfile+10−0
@@ -0,0 +1,10 @@
1+</$objtype/mkfile
2+
3+none:VQ:
4+ echo mk all, install, clean, nuke, installall, update
5+
6+all install clean nuke installall update:V:
7+ @{cd bin/source; mk $target}
8+ @{cd mail/src; mk $target}
9+ @{cd news/src; mk $target}
10+ @{cd wiki/src; mk $target}
acme/news/guide+2−0
@@ -0,0 +1,2 @@
1+Local nntpfs
2+News comp.os.plan9
acme/news/src/6.out+0−0

Binary file not shown.

acme/news/src/8.out+0−0

Binary file not shown.

acme/news/src/mkfile+18−0
@@ -0,0 +1,18 @@
1+</$objtype/mkfile
2+
3+TARG=News
4+OFILES=\
5+ news.$O\
6+ util.$O\
7+ win.$O\
8+
9+HFILES=
10+
11+BIN=/acme/bin/$objtype
12+UPDATE=\
13+ mkfile\
14+ $HFILES\
15+ ${OFILES:%.$O=%.c}\
16+ ${TARG:%=/acme/bin/386/%}\
17+
18+</sys/src/cmd/mkone
acme/news/src/news.6+0−0

Binary file not shown.

acme/news/src/news.8+0−0

Binary file not shown.

acme/news/src/news.c+1007−0
@@ -0,0 +1,1007 @@
1+/*
2+ * Acme interface to nntpfs.
3+ */
4+#include <u.h>
5+#include <libc.h>
6+#include <bio.h>
7+#include <thread.h>
8+#include "win.h"
9+#include <ctype.h>
10+
11+int canpost;
12+int debug;
13+int nshow = 20;
14+
15+int lo; /* next message to look at in dir */
16+int hi; /* current hi message in dir */
17+char *dir = "/mnt/news";
18+char *group;
19+char *from;
20+
21+typedef struct Article Article;
22+struct Article {
23+ Ref;
24+ Article *prev;
25+ Article *next;
26+ Window *w;
27+ int n;
28+ int dead;
29+ int dirtied;
30+ int sayspost;
31+ int headers;
32+ int ispost;
33+};
34+
35+Article *mlist;
36+Window *root;
37+
38+int
39+cistrncmp(char *a, char *b, int n)
40+{
41+ while(n-- > 0){
42+ if(tolower(*a++) != tolower(*b++))
43+ return -1;
44+ }
45+ return 0;
46+}
47+
48+int
49+cistrcmp(char *a, char *b)
50+{
51+ for(;;){
52+ if(tolower(*a) != tolower(*b++))
53+ return -1;
54+ if(*a++ == 0)
55+ break;
56+ }
57+ return 0;
58+}
59+
60+char*
61+skipwhite(char *p)
62+{
63+ while(isspace(*p))
64+ p++;
65+ return p;
66+}
67+
68+int
69+gethi(void)
70+{
71+ Dir *d;
72+ int hi;
73+
74+ if((d = dirstat(dir)) == nil)
75+ return -1;
76+ hi = d->qid.vers;
77+ free(d);
78+ return hi;
79+}
80+
81+char*
82+fixfrom(char *s)
83+{
84+ char *r, *w;
85+
86+ s = estrdup(s);
87+ /* remove quotes */
88+ for(r=w=s; *r; r++)
89+ if(*r != '"')
90+ *w++ = *r;
91+ *w = '\0';
92+ return s;
93+}
94+
95+char *day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", };
96+char *mon[] = {
97+ "Jan", "Feb", "Mar", "Apr",
98+ "May", "Jun", "Jul", "Aug",
99+ "Sep", "Oct", "Nov", "Dec",
100+};
101+
102+char*
103+fixdate(char *s)
104+{
105+ char *f[10], *m, *t, *wd, tmp[40];
106+ int d, i, j, nf, hh, mm;
107+
108+ nf = tokenize(s, f, nelem(f));
109+
110+ wd = nil;
111+ d = 0;
112+ m = nil;
113+ t = nil;
114+ for(i=0; i<nf; i++){
115+ for(j=0; j<7; j++)
116+ if(cistrncmp(day[j], f[i], 3)==0)
117+ wd = day[j];
118+ for(j=0; j<12; j++)
119+ if(cistrncmp(mon[j], f[i], 3)==0)
120+ m = mon[j];
121+ j = atoi(f[i]);
122+ if(1 <= j && j <= 31 && d != 0)
123+ d = j;
124+ if(strchr(f[i], ':'))
125+ t = f[i];
126+ }
127+
128+ if(d==0 || wd==nil || m==nil || t==nil)
129+ return nil;
130+
131+ hh = strtol(t, 0, 10);
132+ mm = strtol(strchr(t, ':')+1, 0, 10);
133+ sprint(tmp, "%s %d %s %d:%.2d", wd, d, m, hh, mm);
134+ return estrdup(tmp);
135+}
136+
137+void
138+msgheadline(Biobuf *bin, int n, Biobuf *bout)
139+{
140+ char *p, *q;
141+ char *date;
142+ char *from;
143+ char *subject;
144+
145+ date = nil;
146+ from = nil;
147+ subject = nil;
148+ while(p = Brdline(bin, '\n')){
149+ p[Blinelen(bin)-1] = '\0';
150+ if((q = strchr(p, ':')) == nil)
151+ continue;
152+ *q++ = '\0';
153+ if(cistrcmp(p, "from")==0)
154+ from = fixfrom(skipwhite(q));
155+ else if(cistrcmp(p, "subject")==0)
156+ subject = estrdup(skipwhite(q));
157+ else if(cistrcmp(p, "date")==0)
158+ date = fixdate(skipwhite(q));
159+ }
160+
161+ Bprint(bout, "%d/\t%s", n, from ? from : "");
162+ if(date)
163+ Bprint(bout, "\t%s", date);
164+ if(subject)
165+ Bprint(bout, "\n\t%s", subject);
166+ Bprint(bout, "\n");
167+
168+ free(date);
169+ free(from);
170+ free(subject);
171+}
172+
173+/*
174+ * Write the headers for at most nshow messages to b,
175+ * starting with hi and working down to lo.
176+ * Return number of first message not scanned.
177+ */
178+int
179+adddir(Biobuf *body, int hi, int lo, int nshow)
180+{
181+ char *p, *q, tmp[40];
182+ int i, n;
183+ Biobuf *b;
184+
185+ n = 0;
186+ for(i=hi; i>=lo && n<nshow; i--){
187+ sprint(tmp, "%d", i);
188+ p = estrstrdup(dir, tmp);
189+ if(access(p, OREAD) < 0){
190+ free(p);
191+ break;
192+ }
193+ q = estrstrdup(p, "/header");
194+ free(p);
195+ b = Bopen(q, OREAD);
196+ free(q);
197+ if(b == nil)
198+ continue;
199+ msgheadline(b, i, body);
200+ Bterm(b);
201+ n++;
202+ }
203+ return i;
204+}
205+
206+/*
207+ * Show the first nshow messages in the window.
208+ * This depends on nntpfs presenting contiguously
209+ * numbered directories, and on the qid version being
210+ * the topmost numbered directory.
211+ */
212+void
213+dirwindow(Window *w)
214+{
215+ if((hi=gethi()) < 0)
216+ return;
217+
218+ if(w->data < 0)
219+ w->data = winopenfile(w, "data");
220+
221+ fprint(w->ctl, "dirty\n");
222+
223+ winopenbody(w, OWRITE);
224+ lo = adddir(w->body, hi, 0, nshow);
225+ winclean(w);
226+}
227+
228+/* return 1 if handled, 0 otherwise */
229+static int
230+iscmd(char *s, char *cmd)
231+{
232+ int len;
233+
234+ len = strlen(cmd);
235+ return strncmp(s, cmd, len)==0 && (s[len]=='\0' || s[len]==' ' || s[len]=='\t' || s[len]=='\n');
236+}
237+
238+static char*
239+skip(char *s, char *cmd)
240+{
241+ s += strlen(cmd);
242+ while(*s==' ' || *s=='\t' || *s=='\n')
243+ s++;
244+ return s;
245+}
246+
247+void
248+unlink(Article *m)
249+{
250+ if(mlist == m)
251+ mlist = m->next;
252+
253+ if(m->next)
254+ m->next->prev = m->prev;
255+ if(m->prev)
256+ m->prev->next = m->next;
257+ m->next = m->prev = nil;
258+}
259+
260+int mesgopen(char*);
261+int fillmesgwindow(int, Article*);
262+Article *newpost(void);
263+void replywindow(Article*);
264+void mesgpost(Article*);
265+
266+/*
267+ * Depends on d.qid.vers being highest numbered message in dir.
268+ */
269+void
270+acmetimer(Article *m, Window *w)
271+{
272+ Biobuf *b;
273+ Dir *d;
274+
275+ assert(m==nil && w==root);
276+
277+ if((d = dirstat(dir))==nil | hi==d->qid.vers){
278+ free(d);
279+ return;
280+ }
281+
282+ if(w->data < 0)
283+ w->data = winopenfile(w, "data");
284+ if(winsetaddr(w, "0", 0))
285+ write(w->data, "", 0);
286+
287+ b = emalloc(sizeof(*b));
288+ Binit(b, w->data, OWRITE);
289+ adddir(b, d->qid.vers, hi+1, d->qid.vers);
290+ hi = d->qid.vers;
291+ Bterm(b);
292+ free(b);
293+ free(d);
294+ winselect(w, "0,.", 0);
295+}
296+
297+int
298+acmeload(Article*, Window*, char *s)
299+{
300+ int nopen;
301+
302+//fprint(2, "load %s\n", s);
303+
304+ nopen = 0;
305+ while(*s){
306+ /* skip directory name */
307+ if(strncmp(s, dir, strlen(dir))==0)
308+ s += strlen(dir);
309+ nopen += mesgopen(s);
310+ if((s = strchr(s, '\n')) == nil)
311+ break;
312+ s = skip(s, "");
313+ }
314+ return nopen;
315+}
316+
317+int
318+acmecmd(Article *m, Window *w, char *s)
319+{
320+ int n;
321+ Biobuf *b;
322+
323+//fprint(2, "cmd %s\n", s);
324+
325+ s = skip(s, "");
326+
327+ if(iscmd(s, "Del")){
328+ if(m == nil){ /* don't close dir until messages close */
329+ if(mlist != nil){
330+ ctlprint(mlist->w->ctl, "show\n");
331+ return 1;
332+ }
333+ if(windel(w, 0))
334+ threadexitsall(nil);
335+ return 1;
336+ }else{
337+ if(windel(w, 0))
338+ m->dead = 1;
339+ return 1;
340+ }
341+ }
342+ if(m==nil && iscmd(s, "More")){
343+ s = skip(s, "More");
344+ if(n = atoi(s))
345+ nshow = n;
346+
347+ if(w->data < 0)
348+ w->data = winopenfile(w, "data");
349+ winsetaddr(w, "$", 1);
350+
351+ fprint(w->ctl, "dirty\n");
352+
353+ b = emalloc(sizeof(*b));
354+ Binit(b, w->data, OWRITE);
355+ lo = adddir(b, lo, 0, nshow);
356+ Bterm(b);
357+ free(b);
358+ winclean(w);
359+ winsetaddr(w, ".,", 0);
360+ }
361+ if(m!=nil && !m->ispost && iscmd(s, "Headers")){
362+ m->headers = !m->headers;
363+ fillmesgwindow(-1, m);
364+ return 1;
365+ }
366+ if(iscmd(s, "Newpost")){
367+ m = newpost();
368+ winopenbody(m->w, OWRITE);
369+ Bprint(m->w->body, "%s\nsubject: \n\n", group);
370+ winclean(m->w);
371+ winselect(m->w, "$", 0);
372+ return 1;
373+ }
374+ if(m!=nil && !m->ispost && iscmd(s, "Reply")){
375+ replywindow(m);
376+ return 1;
377+ }
378+// if(m!=nil && iscmd(s, "Replymail")){
379+// fprint(2, "no replymail yet\n");
380+// return 1;
381+// }
382+ if(iscmd(s, "Post")){
383+ mesgpost(m);
384+ return 1;
385+ }
386+ return 0;
387+}
388+
389+void
390+acmeevent(Article *m, Window *w, Event *e)
391+{
392+ Event *ea, *e2, *eq;
393+ char *s, *t, *buf;
394+ int na;
395+ //int n;
396+ //ulong q0, q1;
397+
398+ switch(e->c1){ /* origin of action */
399+ default:
400+ Unknown:
401+ fprint(2, "unknown message %c%c\n", e->c1, e->c2);
402+ break;
403+
404+ case 'T': /* bogus timer event! */
405+ acmetimer(m, w);
406+ break;
407+
408+ case 'F': /* generated by our actions; ignore */
409+ break;
410+
411+ case 'E': /* write to body or tag; can't affect us */
412+ break;
413+
414+ case 'K': /* type away; we don't care */
415+ if(m && (e->c2 == 'I' || e->c2 == 'D')){
416+ m->dirtied = 1;
417+ if(!m->sayspost){
418+ wintagwrite(w, "Post ", 5);
419+ m->sayspost = 1;
420+ }
421+ }
422+ break;
423+
424+ case 'M': /* mouse event */
425+ switch(e->c2){ /* type of action */
426+ case 'x': /* mouse: button 2 in tag */
427+ case 'X': /* mouse: button 2 in body */
428+ ea = nil;
429+ //e2 = nil;
430+ s = e->b;
431+ if(e->flag & 2){ /* null string with non-null expansion */
432+ e2 = recvp(w->cevent);
433+ if(e->nb==0)
434+ s = e2->b;
435+ }
436+ if(e->flag & 8){ /* chorded argument */
437+ ea = recvp(w->cevent); /* argument */
438+ na = ea->nb;
439+ recvp(w->cevent); /* ignore origin */
440+ }else
441+ na = 0;
442+
443+ /* append chorded arguments */
444+ if(na){
445+ t = emalloc(strlen(s)+1+na+1);
446+ sprint(t, "%s %s", s, ea->b);
447+ s = t;
448+ }
449+ /* if it's a known command, do it */
450+ /* if it's a long message, it can't be for us anyway */
451+ // DPRINT(2, "exec: %s\n", s);
452+ if(!acmecmd(m, w, s)) /* send it back */
453+ winwriteevent(w, e);
454+ if(na)
455+ free(s);
456+ break;
457+
458+ case 'l': /* mouse: button 3 in tag */
459+ case 'L': /* mouse: button 3 in body */
460+ //buf = nil;
461+ eq = e;
462+ if(e->flag & 2){
463+ e2 = recvp(w->cevent);
464+ eq = e2;
465+ }
466+ s = eq->b;
467+ if(eq->q1>eq->q0 && eq->nb==0){
468+ buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
469+ winread(w, eq->q0, eq->q1, buf);
470+ s = buf;
471+ }
472+ if(!acmeload(m, w, s))
473+ winwriteevent(w, e);
474+ break;
475+
476+ case 'i': /* mouse: text inserted in tag */
477+ case 'd': /* mouse: text deleted from tag */
478+ break;
479+
480+ case 'I': /* mouse: text inserted in body */
481+ case 'D': /* mouse: text deleted from body */
482+ if(m == nil)
483+ break;
484+
485+ m->dirtied = 1;
486+ if(!m->sayspost){
487+ wintagwrite(w, "Post ", 5);
488+ m->sayspost = 1;
489+ }
490+ break;
491+
492+ default:
493+ goto Unknown;
494+ }
495+ }
496+}
497+
498+void
499+dirthread(void *v)
500+{
501+ Event *e;
502+ Window *w;
503+
504+ w = v;
505+ while(e = recvp(w->cevent))
506+ acmeevent(nil, w, e);
507+
508+ threadexitsall(nil);
509+}
510+
511+void
512+mesgthread(void *v)
513+{
514+ Event *e;
515+ Article *m;
516+
517+ m = v;
518+ while(!m->dead && (e = recvp(m->w->cevent)))
519+ acmeevent(m, m->w, e);
520+
521+//fprint(2, "msg %p exits\n", m);
522+ unlink(m);
523+ free(m->w);
524+ free(m);
525+ threadexits(nil);
526+}
527+
528+/*
529+Xref: news.research.att.com comp.os.plan9:7360
530+Newsgroups: comp.os.plan9
531+Path: news.research.att.com!batch0!uunet!ffx.uu.net!finch!news.mindspring.net!newsfeed.mathworks.com!fu-berlin.de!server1.netnews.ja.net!hgmp.mrc.ac.uk!pegasus.csx.cam.ac.uk!bath.ac.uk!ccsdhd
532+From: Stephen Adam <saadam@bigpond.com>
533+Subject: Future of Plan9
534+Approved: plan9mod@bath.ac.uk
535+X-Newsreader: Microsoft Outlook Express 5.00.2014.211
536+X-Mimeole: Produced By Microsoft MimeOLE V5.00.2014.211
537+Sender: ccsdhd@bath.ac.uk (Dennis Davis)
538+Nntp-Posting-Date: Wed, 13 Dec 2000 21:28:45 EST
539+NNTP-Posting-Host: 203.54.121.233
540+Organization: Telstra BigPond Internet Services (http://www.bigpond.com)
541+X-Date: Wed, 13 Dec 2000 20:43:37 +1000
542+Lines: 12
543+Message-ID: <xbIZ5.157945$e5.114349@newsfeeds.bigpond.com>
544+References: <95pghu$3lf$1@news.fas.harvard.edu> <95ph36$3m9$1@news.fas.harvard.edu> <slrn980iic.u5q.mperrin@hcs.harvard.edu> <95png6$4ln$1@news.fas.harvard.edu> <95poqg$4rq$1@news.fas.harvard.edu> <slrn980vh8.2gb.myLastName@is07.fas.harvard.edu> <95q40h$66c$2@news.fas.harvard.edu> <95qjhu$8ke$1@news.fas.harvard.edu> <95riue$bu2$1@news.fas.harvard.edu> <95rnar$cbu$1@news.fas.harvard.edu>
545+X-Msmail-Priority: Normal
546+X-Trace: newsfeeds.bigpond.com 976703325 203.54.121.233 (Wed, 13 Dec 2000 21:28:45 EST)
547+X-Priority: 3
548+Date: Wed, 13 Dec 2000 10:49:50 GMT
549+*/
550+
551+char *skipheader[] =
552+{
553+ "x-",
554+ "path:",
555+ "xref:",
556+ "approved:",
557+ "sender:",
558+ "nntp-",
559+ "organization:",
560+ "lines:",
561+ "message-id:",
562+ "references:",
563+ "reply-to:",
564+ "mime-",
565+ "content-",
566+};
567+
568+int
569+fillmesgwindow(int fd, Article *m)
570+{
571+ Biobuf *b;
572+ char *p, tmp[40];
573+ int i, inhdr, copy, xfd;
574+ Window *w;
575+
576+ xfd = -1;
577+ if(fd == -1){
578+ sprint(tmp, "%d/article", m->n);
579+ p = estrstrdup(dir, tmp);
580+ if((xfd = open(p, OREAD)) < 0){
581+ free(p);
582+ return 0;
583+ }
584+ free(p);
585+ fd = xfd;
586+ }
587+
588+ w = m->w;
589+ if(w->data < 0)
590+ w->data = winopenfile(w, "data");
591+ if(winsetaddr(w, ",", 0))
592+ write(w->data, "", 0);
593+
594+ winopenbody(m->w, OWRITE);
595+ b = emalloc(sizeof(*b));
596+ Binit(b, fd, OREAD);
597+
598+ inhdr = 1;
599+ copy = 1;
600+ while(p = Brdline(b, '\n')){
601+ if(Blinelen(b)==1)
602+ inhdr = 0, copy=1;
603+ if(inhdr && !isspace(p[0])){
604+ copy = 1;
605+ if(!m->headers){
606+ if(cistrncmp(p, "from:", 5)==0){
607+ p[Blinelen(b)-1] = '\0';
608+ p = fixfrom(skip(p, "from:"));
609+ Bprint(m->w->body, "From: %s\n", p);
610+ free(p);
611+ copy = 0;
612+ continue;
613+ }
614+ for(i=0; i<nelem(skipheader); i++)
615+ if(cistrncmp(p, skipheader[i], strlen(skipheader[i]))==0)
616+ copy=0;
617+ }
618+ }
619+ if(copy)
620+ Bwrite(m->w->body, p, Blinelen(b));
621+ }
622+ Bterm(b);
623+ free(b);
624+ winclean(m->w);
625+ if(xfd != -1)
626+ close(xfd);
627+ return 1;
628+}
629+
630+Article*
631+newpost(void)
632+{
633+ Article *m;
634+ char *p, tmp[40];
635+ static int nnew;
636+
637+ m = emalloc(sizeof *m);
638+ sprint(tmp, "Post%d", ++nnew);
639+ p = estrstrdup(dir, tmp);
640+
641+ m->w = newwindow();
642+ proccreate(wineventproc, m->w, STACK);
643+ winname(m->w, p);
644+ wintagwrite(m->w, "Post ", 5);
645+ m->sayspost = 1;
646+ m->ispost = 1;
647+ threadcreate(mesgthread, m, STACK);
648+
649+ if(mlist){
650+ m->next = mlist;
651+ mlist->prev = m;
652+ }
653+ mlist = m;
654+ return m;
655+}
656+
657+void
658+replywindow(Article *m)
659+{
660+ Biobuf *b;
661+ char *p, *ep, *q, tmp[40];
662+ int fd, copy;
663+ Article *reply;
664+
665+ sprint(tmp, "%d/article", m->n);
666+ p = estrstrdup(dir, tmp);
667+ if((fd = open(p, OREAD)) < 0){
668+ free(p);
669+ return;
670+ }
671+ free(p);
672+
673+ reply = newpost();
674+ winopenbody(reply->w, OWRITE);
675+ b = emalloc(sizeof(*b));
676+ Binit(b, fd, OREAD);
677+ copy = 0;
678+ while(p = Brdline(b, '\n')){
679+ if(Blinelen(b)==1)
680+ break;
681+ ep = p+Blinelen(b);
682+ if(!isspace(*p)){
683+ copy = 0;
684+ if(cistrncmp(p, "newsgroups:", 11)==0){
685+ for(q=p+11; *q!='\n'; q++)
686+ if(*q==',')
687+ *q = ' ';
688+ copy = 1;
689+ }else if(cistrncmp(p, "subject:", 8)==0){
690+ if(!strstr(p, " Re:") && !strstr(p, " RE:") && !strstr(p, " re:")){
691+ p = skip(p, "subject:");
692+ ep[-1] = '\0';
693+ Bprint(reply->w->body, "Subject: Re: %s\n", p);
694+ }else
695+ copy = 1;
696+ }else if(cistrncmp(p, "message-id:", 11)==0){
697+ Bprint(reply->w->body, "References: ");
698+ p += 11;
699+ copy = 1;
700+ }
701+ }
702+ if(copy)
703+ Bwrite(reply->w->body, p, ep-p);
704+ }
705+ Bterm(b);
706+ close(fd);
707+ free(b);
708+ Bprint(reply->w->body, "\n");
709+ winclean(reply->w);
710+ winselect(reply->w, "$", 0);
711+}
712+
713+char*
714+skipbl(char *s, char *e)
715+{
716+ while(s < e){
717+ if(*s!=' ' && *s!='\t' && *s!=',')
718+ break;
719+ s++;
720+ }
721+ return s;
722+}
723+
724+char*
725+findbl(char *s, char *e)
726+{
727+ while(s < e){
728+ if(*s==' ' || *s=='\t' || *s==',')
729+ break;
730+ s++;
731+ }
732+ return s;
733+}
734+
735+/*
736+ * comma-separate possibly blank-separated strings in line; e points before newline
737+ */
738+void
739+commas(char *s, char *e)
740+{
741+ char *t;
742+
743+ /* may have initial blanks */
744+ s = skipbl(s, e);
745+ while(s < e){
746+ s = findbl(s, e);
747+ if(s == e)
748+ break;
749+ t = skipbl(s, e);
750+ if(t == e) /* no more words */
751+ break;
752+ /* patch comma */
753+ *s++ = ',';
754+ while(s < t)
755+ *s++ = ' ';
756+ }
757+}
758+void
759+mesgpost(Article *m)
760+{
761+ Biobuf *b;
762+ char *p, *ep;
763+ int isfirst, ishdr, havegroup, havefrom;
764+
765+ p = estrstrdup(dir, "post");
766+ if((b = Bopen(p, OWRITE)) == nil){
767+ fprint(2, "cannot open %s: %r\n", p);
768+ free(p);
769+ return;
770+ }
771+ free(p);
772+
773+ winopenbody(m->w, OREAD);
774+ ishdr = 1;
775+ isfirst = 1;
776+ havegroup = havefrom = 0;
777+ while(p = Brdline(m->w->body, '\n')){
778+ ep = p+Blinelen(m->w->body);
779+ if(ishdr && p+1==ep){
780+ if(!havegroup)
781+ Bprint(b, "Newsgroups: %s\n", group);
782+ if(!havefrom)
783+ Bprint(b, "From: %s\n", from);
784+ ishdr = 0;
785+ }
786+ if(ishdr){
787+ ep[-1] = '\0';
788+ if(isfirst && strchr(p, ':')==0){ /* group list */
789+ commas(p, ep);
790+ Bprint(b, "newsgroups: %s\n", p);
791+ havegroup = 1;
792+ isfirst = 0;
793+ continue;
794+ }
795+ if(cistrncmp(p, "newsgroup:", 10)==0){
796+ commas(skip(p, "newsgroup:"), ep);
797+ Bprint(b, "newsgroups: %s\n", skip(p, "newsgroup:"));
798+ havegroup = 1;
799+ continue;
800+ }
801+ if(cistrncmp(p, "newsgroups:", 11)==0){
802+ commas(skip(p, "newsgroups:"), ep);
803+ Bprint(b, "newsgroups: %s\n", skip(p, "newsgroups:"));
804+ havegroup = 1;
805+ continue;
806+ }
807+ if(cistrncmp(p, "from:", 5)==0)
808+ havefrom = 1;
809+ ep[-1] = '\n';
810+ }
811+ Bwrite(b, p, ep-p);
812+ }
813+ winclosebody(m->w);
814+ Bflush(b);
815+ if(write(Bfildes(b), "", 0) == 0)
816+ winclean(m->w);
817+ else
818+ fprint(2, "post: %r\n");
819+ Bterm(b);
820+}
821+
822+int
823+mesgopen(char *s)
824+{
825+ char *p, tmp[40];
826+ int fd, n;
827+ Article *m;
828+
829+ n = atoi(s);
830+ if(n==0)
831+ return 0;
832+
833+ for(m=mlist; m; m=m->next){
834+ if(m->n == n){
835+ ctlprint(m->w->ctl, "show\n");
836+ return 1;
837+ }
838+ }
839+
840+ sprint(tmp, "%d/article", n);
841+ p = estrstrdup(dir, tmp);
842+ if((fd = open(p, OREAD)) < 0){
843+ free(p);
844+ return 0;
845+ }
846+
847+ m = emalloc(sizeof(*m));
848+ m->w = newwindow();
849+ m->n = n;
850+ proccreate(wineventproc, m->w, STACK);
851+ p[strlen(p)-strlen("article")] = '\0';
852+ winname(m->w, p);
853+ if(canpost)
854+ wintagwrite(m->w, "Reply ", 6);
855+ wintagwrite(m->w, "Headers ", 8);
856+
857+ free(p);
858+ if(mlist){
859+ m->next = mlist;
860+ mlist->prev = m;
861+ }
862+ mlist = m;
863+ threadcreate(mesgthread, m, STACK);
864+
865+ fillmesgwindow(fd, m);
866+ close(fd);
867+ windormant(m->w);
868+ return 1;
869+}
870+
871+void
872+usage(void)
873+{
874+ fprint(2, "usage: News [-d /mnt/news] comp.os.plan9\n");
875+ exits("usage");
876+}
877+
878+void
879+timerproc(void *v)
880+{
881+ Event e;
882+ Window *w;
883+
884+ memset(&e, 0, sizeof e);
885+ e.c1 = 'T';
886+ w = v;
887+
888+ for(;;){
889+ sleep(60*1000);
890+ sendp(w->cevent, &e);
891+ }
892+}
893+
894+char*
895+findfrom(void)
896+{
897+ char *p, *u;
898+ Biobuf *b;
899+
900+ u = getuser();
901+ if(u==nil)
902+ return "glenda";
903+
904+ p = estrstrstrdup("/usr/", u, "/lib/newsfrom");
905+ b = Bopen(p, OREAD);
906+ free(p);
907+ if(b){
908+ p = Brdline(b, '\n');
909+ if(p){
910+ p[Blinelen(b)-1] = '\0';
911+ p = estrdup(p);
912+ Bterm(b);
913+ return p;
914+ }
915+ Bterm(b);
916+ }
917+
918+ p = estrstrstrdup("/mail/box/", u, "/headers");
919+ b = Bopen(p, OREAD);
920+ free(p);
921+ if(b){
922+ while(p = Brdline(b, '\n')){
923+ p[Blinelen(b)-1] = '\0';
924+ if(cistrncmp(p, "from:", 5)==0){
925+ p = estrdup(skip(p, "from:"));
926+ Bterm(b);
927+ return p;
928+ }
929+ }
930+ Bterm(b);
931+ }
932+
933+ return u;
934+}
935+
936+void
937+threadmain(int argc, char **argv)
938+{
939+ char *p, *q;
940+ Dir *d;
941+ Window *w;
942+
943+ ARGBEGIN{
944+ case 'D':
945+ debug++;
946+ break;
947+ case 'd':
948+ dir = EARGF(usage());
949+ break;
950+ default:
951+ usage();
952+ break;
953+ }ARGEND
954+
955+ if(argc != 1)
956+ usage();
957+
958+ from = findfrom();
959+
960+ group = estrdup(argv[0]); /* someone will be cute */
961+ while(q=strchr(group, '/'))
962+ *q = '.';
963+
964+ p = estrdup(argv[0]);
965+ while(q=strchr(p, '.'))
966+ *q = '/';
967+ p = estrstrstrdup(dir, "/", p);
968+ cleanname(p);
969+
970+ if((d = dirstat(p)) == nil){ /* maybe it is a new group */
971+ if((d = dirstat(dir)) == nil){
972+ fprint(2, "dirstat(%s) fails: %r\n", dir);
973+ threadexitsall(nil);
974+ }
975+ if((d->mode&DMDIR)==0){
976+ fprint(2, "%s not a directory\n", dir);
977+ threadexitsall(nil);
978+ }
979+ free(d);
980+ if((d = dirstat(p)) == nil){
981+ fprint(2, "stat %s: %r\n", p);
982+ threadexitsall(nil);
983+ }
984+ }
985+ if((d->mode&DMDIR)==0){
986+ fprint(2, "%s not a directory\n", dir);
987+ threadexitsall(nil);
988+ }
989+ free(d);
990+ dir = estrstrdup(p, "/");
991+
992+ q = estrstrdup(dir, "post");
993+ canpost = access(q, AWRITE)==0;
994+
995+ w = newwindow();
996+ root = w;
997+ proccreate(wineventproc, w, STACK);
998+ proccreate(timerproc, w, STACK);
999+
1000+ winname(w, dir);
1001+ if(canpost)
1002+ wintagwrite(w, "Newpost ", 8);
1003+ wintagwrite(w, "More ", 5);
1004+ dirwindow(w);
1005+ threadcreate(dirthread, w, STACK);
1006+ threadexits(nil);
1007+}
acme/news/src/util.6+0−0

Binary file not shown.

acme/news/src/util.8+0−0

Binary file not shown.

acme/news/src/util.c+106−0
@@ -0,0 +1,106 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include "win.h"
6+
7+void*
8+emalloc(uint n)
9+{
10+ void *p;
11+
12+ p = malloc(n);
13+ if(p == nil)
14+ error("can't malloc: %r");
15+ memset(p, 0, n);
16+ return p;
17+}
18+
19+char*
20+estrdup(char *s)
21+{
22+ char *t;
23+
24+ t = emalloc(strlen(s)+1);
25+ strcpy(t, s);
26+ return t;
27+}
28+
29+char*
30+estrstrdup(char *s, char *t)
31+{
32+ char *u;
33+
34+ u = emalloc(strlen(s)+strlen(t)+1);
35+ strcpy(u, s);
36+ strcat(u, t);
37+ return u;
38+}
39+
40+char*
41+estrstrstrdup(char *r, char *s, char *t)
42+{
43+ char *u;
44+
45+ u = emalloc(strlen(r)+strlen(s)+strlen(t)+1);
46+ strcpy(u, r);
47+ strcat(u, s);
48+ strcat(u, t);
49+ return u;
50+}
51+
52+char*
53+eappend(char *s, char *sep, char *t)
54+{
55+ char *u;
56+
57+ if(t == nil)
58+ u = estrstrdup(s, sep);
59+ else{
60+ u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1);
61+ strcpy(u, s);
62+ strcat(u, sep);
63+ strcat(u, t);
64+ }
65+ free(s);
66+ return u;
67+}
68+
69+char*
70+egrow(char *s, char *sep, char *t)
71+{
72+ s = eappend(s, sep, t);
73+ free(t);
74+ return s;
75+}
76+
77+void
78+error(char *fmt, ...)
79+{
80+ va_list arg;
81+ char buf[256];
82+ Fmt f;
83+
84+ fmtfdinit(&f, 2, buf, sizeof buf);
85+ fmtprint(&f, "%s: ", argv0);
86+ va_start(arg, fmt);
87+ fmtprint(&f, fmt, arg);
88+ va_end(arg);
89+ fmtprint(&f, "\n");
90+ fmtfdflush(&f);
91+ threadexitsall(buf);
92+}
93+
94+void
95+ctlprint(int fd, char *fmt, ...)
96+{
97+ int n;
98+ va_list arg;
99+ char buf[256];
100+
101+ va_start(arg, fmt);
102+ n = vfprint(fd, fmt, arg);
103+ va_end(arg);
104+ if(n < 0)
105+ error("control file write(%s) error: %r", buf);
106+}
acme/news/src/win.6+0−0

Binary file not shown.

acme/news/src/win.8+0−0

Binary file not shown.

acme/news/src/win.c+324−0
@@ -0,0 +1,324 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+#include "win.h"
6+
7+Window*
8+newwindow(void)
9+{
10+ char buf[12];
11+ Window *w;
12+
13+ w = emalloc(sizeof(Window));
14+ w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC);
15+ if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
16+ error("can't open window ctl file: %r");
17+ ctlprint(w->ctl, "noscroll\n");
18+ w->id = atoi(buf);
19+ w->event = winopenfile(w, "event");
20+ w->addr = -1; /* will be opened when needed */
21+ w->body = nil;
22+ w->data = -1;
23+ w->cevent = chancreate(sizeof(Event*), 0);
24+ if(w->cevent == nil)
25+ error("cevent is nil: %r");
26+ return w;
27+}
28+
29+void
30+winsetdump(Window *w, char *dir, char *cmd)
31+{
32+ if(dir != nil)
33+ ctlprint(w->ctl, "dumpdir %s\n", dir);
34+ if(cmd != nil)
35+ ctlprint(w->ctl, "dump %s\n", cmd);
36+}
37+
38+void
39+wineventproc(void *v)
40+{
41+ Window *w;
42+ int i;
43+
44+ threadsetname("wineventproc");
45+ w = v;
46+ for(i=0; ; i++){
47+ if(i >= NEVENT)
48+ i = 0;
49+ wingetevent(w, &w->e[i]);
50+ sendp(w->cevent, &w->e[i]);
51+ }
52+}
53+
54+int
55+winopenfile(Window *w, char *f)
56+{
57+ char buf[64];
58+ int fd;
59+
60+ sprint(buf, "/mnt/wsys/%d/%s", w->id, f);
61+ fd = open(buf, ORDWR|OCEXEC);
62+ if(fd < 0)
63+ error("can't open window file %s: %r", f);
64+ return fd;
65+}
66+
67+void
68+wintagwrite(Window *w, char *s, int n)
69+{
70+ int fd;
71+
72+ fd = winopenfile(w, "tag");
73+ if(write(fd, s, n) != n)
74+ error("tag write: %r");
75+ close(fd);
76+}
77+
78+void
79+winname(Window *w, char *s)
80+{
81+ ctlprint(w->ctl, "name %s\n", s);
82+}
83+
84+void
85+winopenbody(Window *w, int mode)
86+{
87+ char buf[256];
88+
89+ sprint(buf, "/mnt/wsys/%d/body", w->id);
90+ w->body = Bopen(buf, mode|OCEXEC);
91+ if(w->body == nil)
92+ error("can't open window body file: %r");
93+}
94+
95+void
96+winclosebody(Window *w)
97+{
98+ if(w->body != nil){
99+ Bterm(w->body);
100+ w->body = nil;
101+ }
102+}
103+
104+void
105+winwritebody(Window *w, char *s, int n)
106+{
107+ if(w->body == nil)
108+ winopenbody(w, OWRITE);
109+ if(Bwrite(w->body, s, n) != n)
110+ error("write error to window: %r");
111+}
112+
113+int
114+wingetec(Window *w)
115+{
116+ if(w->nbuf == 0){
117+ w->nbuf = read(w->event, w->buf, sizeof w->buf);
118+ if(w->nbuf <= 0){
119+ /* probably because window has exited, and only called by wineventproc, so just shut down */
120+ threadexits(nil);
121+ }
122+ w->bufp = w->buf;
123+ }
124+ w->nbuf--;
125+ return *w->bufp++;
126+}
127+
128+int
129+wingeten(Window *w)
130+{
131+ int n, c;
132+
133+ n = 0;
134+ while('0'<=(c=wingetec(w)) && c<='9')
135+ n = n*10+(c-'0');
136+ if(c != ' ')
137+ error("event number syntax");
138+ return n;
139+}
140+
141+int
142+wingeter(Window *w, char *buf, int *nb)
143+{
144+ Rune r;
145+ int n;
146+
147+ r = wingetec(w);
148+ buf[0] = r;
149+ n = 1;
150+ if(r >= Runeself) {
151+ while(!fullrune(buf, n))
152+ buf[n++] = wingetec(w);
153+ chartorune(&r, buf);
154+ }
155+ *nb = n;
156+ return r;
157+}
158+
159+void
160+wingetevent(Window *w, Event *e)
161+{
162+ int i, nb;
163+
164+ e->c1 = wingetec(w);
165+ e->c2 = wingetec(w);
166+ e->q0 = wingeten(w);
167+ e->q1 = wingeten(w);
168+ e->flag = wingeten(w);
169+ e->nr = wingeten(w);
170+ if(e->nr > EVENTSIZE)
171+ error("event string too long");
172+ e->nb = 0;
173+ for(i=0; i<e->nr; i++){
174+ e->r[i] = wingeter(w, e->b+e->nb, &nb);
175+ e->nb += nb;
176+ }
177+ e->r[e->nr] = 0;
178+ e->b[e->nb] = 0;
179+ if(wingetec(w) != '\n')
180+ error("event syntax error");
181+}
182+
183+void
184+winwriteevent(Window *w, Event *e)
185+{
186+ fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
187+}
188+
189+static int
190+nrunes(char *s, int nb)
191+{
192+ int i, n;
193+ Rune r;
194+
195+ n = 0;
196+ for(i=0; i<nb; n++)
197+ i += chartorune(&r, s+i);
198+ return n;
199+}
200+
201+void
202+winread(Window *w, uint q0, uint q1, char *data)
203+{
204+ int m, n, nr;
205+ char buf[256];
206+
207+ if(w->addr < 0)
208+ w->addr = winopenfile(w, "addr");
209+ if(w->data < 0)
210+ w->data = winopenfile(w, "data");
211+ m = q0;
212+ while(m < q1){
213+ n = sprint(buf, "#%d", m);
214+ if(write(w->addr, buf, n) != n)
215+ error("error writing addr: %r");
216+ n = read(w->data, buf, sizeof buf);
217+ if(n <= 0)
218+ error("reading data: %r");
219+ nr = nrunes(buf, n);
220+ while(m+nr >q1){
221+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
222+ --nr;
223+ }
224+ if(n == 0)
225+ break;
226+ memmove(data, buf, n);
227+ data += n;
228+ *data = 0;
229+ m += nr;
230+ }
231+}
232+
233+void
234+windormant(Window *w)
235+{
236+ if(w->addr >= 0){
237+ close(w->addr);
238+ w->addr = -1;
239+ }
240+ if(w->body != nil){
241+ Bterm(w->body);
242+ w->body = nil;
243+ }
244+ if(w->data >= 0){
245+ close(w->data);
246+ w->data = -1;
247+ }
248+}
249+
250+
251+int
252+windel(Window *w, int sure)
253+{
254+ if(sure)
255+ write(w->ctl, "delete\n", 7);
256+ else if(write(w->ctl, "del\n", 4) != 4)
257+ return 0;
258+ /* event proc will die due to read error from event file */
259+ windormant(w);
260+ close(w->ctl);
261+ w->ctl = -1;
262+ close(w->event);
263+ w->event = -1;
264+ return 1;
265+}
266+
267+void
268+winclean(Window *w)
269+{
270+ if(w->body)
271+ Bflush(w->body);
272+ ctlprint(w->ctl, "clean\n");
273+}
274+
275+int
276+winsetaddr(Window *w, char *addr, int errok)
277+{
278+ if(w->addr < 0)
279+ w->addr = winopenfile(w, "addr");
280+ if(write(w->addr, addr, strlen(addr)) < 0){
281+ if(!errok)
282+ error("error writing addr(%s): %r", addr);
283+ return 0;
284+ }
285+ return 1;
286+}
287+
288+int
289+winselect(Window *w, char *addr, int errok)
290+{
291+ if(winsetaddr(w, addr, errok)){
292+ ctlprint(w->ctl, "dot=addr\n");
293+ return 1;
294+ }
295+ return 0;
296+}
297+
298+char*
299+winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */
300+{
301+ char *s;
302+ int m, na, n;
303+
304+ if(w->body != nil)
305+ winclosebody(w);
306+ winopenbody(w, OREAD);
307+ s = nil;
308+ na = 0;
309+ n = 0;
310+ for(;;){
311+ if(na < n+512){
312+ na += 1024;
313+ s = realloc(s, na+1);
314+ }
315+ m = Bread(w->body, s+n, na-n);
316+ if(m <= 0)
317+ break;
318+ n += m;
319+ }
320+ s[n] = 0;
321+ winclosebody(w);
322+ *np = n;
323+ return s;
324+}
acme/news/src/win.h+75−0
@@ -0,0 +1,75 @@
1+/* acme */
2+typedef struct Event Event;
3+typedef struct Window Window;
4+
5+enum
6+{
7+ STACK = 8192,
8+ EVENTSIZE = 256,
9+ NEVENT = 5,
10+};
11+
12+struct Event
13+{
14+ int c1;
15+ int c2;
16+ int q0;
17+ int q1;
18+ int flag;
19+ int nb;
20+ int nr;
21+ char b[EVENTSIZE*UTFmax+1];
22+ Rune r[EVENTSIZE+1];
23+};
24+
25+struct Window
26+{
27+ /* file descriptors */
28+ int ctl;
29+ int event;
30+ int addr;
31+ int data;
32+ Biobuf *body;
33+
34+ /* event input */
35+ char buf[512];
36+ char *bufp;
37+ int nbuf;
38+ Event e[NEVENT];
39+
40+ int dirtied;
41+ int id;
42+ int open;
43+ Channel *cevent; /* chan(Event*) */
44+};
45+
46+extern Window* newwindow(void);
47+extern int winopenfile(Window*, char*);
48+extern void winopenbody(Window*, int);
49+extern void winclosebody(Window*);
50+extern void wintagwrite(Window*, char*, int);
51+extern void winname(Window*, char*);
52+extern void winwriteevent(Window*, Event*);
53+extern void winread(Window*, uint, uint, char*);
54+extern int windel(Window*, int);
55+extern void wingetevent(Window*, Event*);
56+extern void wineventproc(void*);
57+extern void winwritebody(Window*, char*, int);
58+extern void winclean(Window*);
59+extern int winselect(Window*, char*, int);
60+extern int winsetaddr(Window*, char*, int);
61+extern char* winreadbody(Window*, int*);
62+extern void windormant(Window*);
63+extern void winsetdump(Window*, char*, char*);
64+
65+extern char* readfile(char*, char*, int*);
66+extern void ctlprint(int, char*, ...);
67+extern void* emalloc(uint);
68+extern char* estrdup(char*);
69+extern char* estrstrdup(char*, char*);
70+extern char* estrstrstrdup(char*, char*, char*);
71+extern char* egrow(char*, char*, char*);
72+extern char* eappend(char*, char*, char*);
73+extern void error(char*, ...);
74+extern int tokenizec(char*, char**, int, char*);
75+
acme/wiki/guide+3−0
@@ -0,0 +1,3 @@
1+Local 9fs wiki
2+# Local wikifs /sys/lib/wiki
3+Wiki /mnt/wiki
acme/wiki/src/6.out+0−0

Binary file not shown.

acme/wiki/src/8.out+0−0

Binary file not shown.

acme/wiki/src/awiki.h+114−0
@@ -0,0 +1,114 @@
1+#include <u.h>
2+#include <libc.h>
3+#include <bio.h>
4+#include <thread.h>
5+
6+/* acme */
7+typedef struct Event Event;
8+typedef struct Window Window;
9+
10+enum
11+{
12+ STACK = 8192,
13+ EVENTSIZE = 256,
14+ NEVENT = 5,
15+};
16+
17+struct Event
18+{
19+ int c1;
20+ int c2;
21+ int q0;
22+ int q1;
23+ int flag;
24+ int nb;
25+ int nr;
26+ char b[EVENTSIZE*UTFmax+1];
27+ Rune r[EVENTSIZE+1];
28+};
29+
30+struct Window
31+{
32+ /* file descriptors */
33+ int ctl;
34+ int event;
35+ int addr;
36+ int data;
37+ Biobuf *body;
38+
39+ /* event input */
40+ char buf[512];
41+ char *bufp;
42+ int nbuf;
43+ Event e[NEVENT];
44+
45+ int warned;
46+ int id;
47+ int open;
48+ Channel *cevent; /* chan(Event*) */
49+};
50+
51+extern Window* newwindow(void);
52+extern int winopenfile(Window*, char*);
53+extern void winopenbody(Window*, int);
54+extern void winclosebody(Window*);
55+extern void wintagwrite(Window*, char*, int);
56+extern void winname(Window*, char*);
57+extern void winwriteevent(Window*, Event*);
58+extern void winread(Window*, uint, uint, char*);
59+extern int windel(Window*, int);
60+extern void wingetevent(Window*, Event*);
61+extern void wineventproc(void*);
62+extern void winwritebody(Window*, char*, int);
63+extern void winclean(Window*);
64+extern int winisdirty(Window*);
65+extern int winselect(Window*, char*, int);
66+extern int winsetaddr(Window*, char*, int);
67+extern char* winreadbody(Window*, int*);
68+extern void windormant(Window*);
69+extern void winsetdump(Window*, char*, char*);
70+
71+extern char* readfile(char*, char*, int*);
72+extern void ctlprint(int, char*, ...);
73+extern void* emalloc(uint);
74+extern char* estrdup(char*);
75+extern char* estrstrdup(char*, char*);
76+extern char* egrow(char*, char*, char*);
77+extern char* eappend(char*, char*, char*);
78+extern void error(char*, ...);
79+extern int tokenizec(char*, char**, int, char*);
80+
81+typedef struct Treq Treq;
82+typedef struct Wiki Wiki;
83+
84+struct Treq {
85+ char *title;
86+ Channel *c; /* chan(int) */
87+};
88+
89+struct Wiki {
90+ QLock;
91+ int isnew;
92+ int special;
93+ char *arg;
94+ char *addr;
95+ int n;
96+ int dead;
97+ Window *win;
98+ ulong time;
99+ int linked;
100+ Wiki *next;
101+ Wiki *prev;
102+};
103+
104+extern int debug;
105+extern int mapfd;
106+extern char *email;
107+extern char *dir;
108+
109+void wikinew(char*);
110+int wikiopen(char*, char*);
111+int wikiput(Wiki*);
112+void wikiget(Wiki*);
113+int wikidiff(Wiki*);
114+
acme/wiki/src/main.6+0−0

Binary file not shown.

acme/wiki/src/main.8+0−0

Binary file not shown.

acme/wiki/src/main.c+60−0
@@ -0,0 +1,60 @@
1+#include "awiki.h"
2+
3+int debug;
4+int mapfd;
5+char *email;
6+char *dir;
7+
8+void
9+usage(void)
10+{
11+ fprint(2, "usage: Wiki [-e email] [dir]\n");
12+ exits("usage");
13+}
14+
15+void
16+threadmain(int argc, char **argv)
17+{
18+ char *s;
19+ Dir *d;
20+
21+ rfork(RFNAMEG);
22+ ARGBEGIN{
23+ case 'D':
24+ debug++;
25+ break;
26+ case 'e':
27+ email = EARGF(usage());
28+ break;
29+ default:
30+ usage();
31+ break;
32+ }ARGEND
33+
34+ if(argc > 1)
35+ usage();
36+ if(argc == 1)
37+ dir = argv[0];
38+ else
39+ dir = "/mnt/wiki";
40+
41+ if(chdir(dir) < 0){
42+ fprint(2, "chdir(%s) fails: %r\n", dir);
43+ threadexitsall(nil);
44+ }
45+
46+ if((mapfd = open("map", ORDWR)) < 0){
47+ fprint(2, "open(map): %r\n");
48+ threadexitsall(nil);
49+ }
50+
51+ if((d = dirstat("1")) == nil){
52+ fprint(2, "dirstat(%s/1) fails: %r\n", dir);
53+ threadexitsall(nil);
54+ }
55+ s = emalloc(strlen(d->name)+2);
56+ strcpy(s, d->name);
57+ strcat(s, "/");
58+ wikiopen(s, nil);
59+ threadexits(nil);
60+}
acme/wiki/src/mkfile+14−0
@@ -0,0 +1,14 @@
1+</$objtype/mkfile
2+
3+TARG=Wiki
4+
5+OFILES=\
6+ main.$O\
7+ util.$O\
8+ wiki.$O\
9+ win.$O\
10+
11+HFILES=awiki.h
12+BIN=../../bin/$objtype
13+
14+</sys/src/cmd/mkone
acme/wiki/src/util.6+0−0

Binary file not shown.

acme/wiki/src/util.8+0−0

Binary file not shown.

acme/wiki/src/util.c+89−0
@@ -0,0 +1,89 @@
1+#include "awiki.h"
2+
3+void*
4+emalloc(uint n)
5+{
6+ void *p;
7+
8+ p = malloc(n);
9+ if(p == nil)
10+ error("can't malloc: %r");
11+ memset(p, 0, n);
12+ return p;
13+}
14+
15+char*
16+estrdup(char *s)
17+{
18+ char *t;
19+
20+ t = emalloc(strlen(s)+1);
21+ strcpy(t, s);
22+ return t;
23+}
24+
25+char*
26+estrstrdup(char *s, char *t)
27+{
28+ char *u;
29+
30+ u = emalloc(strlen(s)+strlen(t)+1);
31+ strcpy(u, s);
32+ strcat(u, t);
33+ return u;
34+}
35+
36+char*
37+eappend(char *s, char *sep, char *t)
38+{
39+ char *u;
40+
41+ if(t == nil)
42+ u = estrstrdup(s, sep);
43+ else{
44+ u = emalloc(strlen(s)+strlen(sep)+strlen(t)+1);
45+ strcpy(u, s);
46+ strcat(u, sep);
47+ strcat(u, t);
48+ }
49+ free(s);
50+ return u;
51+}
52+
53+char*
54+egrow(char *s, char *sep, char *t)
55+{
56+ s = eappend(s, sep, t);
57+ free(t);
58+ return s;
59+}
60+
61+void
62+error(char *fmt, ...)
63+{
64+ int n;
65+ va_list arg;
66+ char buf[256];
67+
68+ fprint(2, "Wiki: ");
69+ va_start(arg, fmt);
70+ n = vseprint(buf, buf+sizeof buf, fmt, arg) - buf;
71+ va_end(arg);
72+ write(2, buf, n);
73+ write(2, "\n", 1);
74+ threadexitsall(buf);
75+}
76+
77+void
78+ctlprint(int fd, char *fmt, ...)
79+{
80+ int n;
81+ va_list arg;
82+ char buf[256];
83+
84+ va_start(arg, fmt);
85+ n = vseprint(buf, buf+sizeof buf, fmt, arg) - buf;
86+ va_end(arg);
87+ if(write(fd, buf, n) != n)
88+ error("control file write(%s) error: %r", buf);
89+}
acme/wiki/src/wiki.6+0−0

Binary file not shown.

acme/wiki/src/wiki.8+0−0

Binary file not shown.

acme/wiki/src/wiki.c+602−0
@@ -0,0 +1,602 @@
1+#include "awiki.h"
2+
3+Wiki *wlist;
4+
5+void
6+link(Wiki *w)
7+{
8+ if(w->linked)
9+ return;
10+ w->linked = 1;
11+ w->prev = nil;
12+ w->next = wlist;
13+ if(wlist)
14+ wlist->prev = w;
15+ wlist = w;
16+}
17+
18+void
19+unlink(Wiki *w)
20+{
21+ if(!w->linked)
22+ return;
23+ w->linked = 0;
24+
25+ if(w->next)
26+ w->next->prev = w->prev;
27+ if(w->prev)
28+ w->prev->next = w->next;
29+ else
30+ wlist = w->next;
31+
32+ w->next = nil;
33+ w->prev = nil;
34+}
35+
36+void
37+wikiname(Window *w, char *name)
38+{
39+ char *p, *q;
40+
41+ p = emalloc(strlen(dir)+1+strlen(name)+1+1);
42+ strcpy(p, dir);
43+ strcat(p, "/");
44+ strcat(p, name);
45+ for(q=p; *q; q++)
46+ if(*q==' ')
47+ *q = '_';
48+ winname(w, p);
49+ free(p);
50+}
51+
52+int
53+wikiput(Wiki *w)
54+{
55+ int fd, n;
56+ char buf[1024], *p;
57+ Biobuf *b;
58+
59+ if((fd = open("new", ORDWR)) < 0){
60+ fprint(2, "Wiki: cannot open raw: %r\n");
61+ return -1;
62+ }
63+
64+ winopenbody(w->win, OREAD);
65+ b = w->win->body;
66+ if((p = Brdline(b, '\n'))==nil){
67+ Short:
68+ winclosebody(w->win);
69+ fprint(2, "Wiki: no data\n");
70+ close(fd);
71+ return -1;
72+ }
73+ write(fd, p, Blinelen(b));
74+
75+ snprint(buf, sizeof buf, "D%lud\n", w->time);
76+ if(email)
77+ snprint(buf+strlen(buf), sizeof(buf)-strlen(buf), "A%s\n", email);
78+
79+ if(Bgetc(b) == '#'){
80+ p = Brdline(b, '\n');
81+ if(p == nil)
82+ goto Short;
83+ snprint(buf+strlen(buf), sizeof(buf)-strlen(buf), "C%s\n", p);
84+ }
85+ write(fd, buf, strlen(buf));
86+ write(fd, "\n\n", 2);
87+
88+ while((n = Bread(b, buf, sizeof buf)) > 0)
89+ write(fd, buf, n);
90+ winclosebody(w->win);
91+
92+ werrstr("");
93+ if((n=write(fd, "", 0)) != 0){
94+ fprint(2, "Wiki commit %lud %d %d: %r\n", w->time, fd, n);
95+ close(fd);
96+ return -1;
97+ }
98+ seek(fd, 0, 0);
99+ if((n = read(fd, buf, 300)) < 0){
100+ fprint(2, "Wiki readback: %r\n");
101+ close(fd);
102+ return -1;
103+ }
104+ close(fd);
105+ buf[n] = '\0';
106+ sprint(buf, "%s/", buf);
107+ free(w->arg);
108+ w->arg = estrdup(buf);
109+ w->isnew = 0;
110+ wikiget(w);
111+ wikiname(w->win, w->arg);
112+ return n;
113+}
114+
115+void
116+wikiget(Wiki *w)
117+{
118+ char *p;
119+ int fd, normal;
120+ Biobuf *bin;
121+
122+ fprint(w->win->ctl, "dirty\n");
123+
124+ p = emalloc(strlen(w->arg)+8+1);
125+ strcpy(p, w->arg);
126+ normal = 1;
127+ if(p[strlen(p)-1] == '/'){
128+ normal = 0;
129+ strcat(p, "current");
130+ }else if(strlen(p)>8 && strcmp(p+strlen(p)-8, "/current")==0){
131+ normal = 0;
132+ w->arg[strlen(w->arg)-7] = '\0';
133+ }
134+
135+ if((fd = open(p, OREAD)) < 0){
136+ fprint(2, "Wiki: cannot read %s: %r\n", p);
137+ winclean(w->win);
138+ return;
139+ }
140+ free(p);
141+
142+ winopenbody(w->win, OWRITE);
143+ bin = emalloc(sizeof(*bin));
144+ Binit(bin, fd, OREAD);
145+
146+ p = nil;
147+ if(!normal){
148+ if((p = Brdline(bin, '\n')) == nil){
149+ fprint(2, "Wiki: cannot read title: %r\n");
150+ winclean(w->win);
151+ close(fd);
152+ free(bin);
153+ return;
154+ }
155+ p[Blinelen(bin)-1] = '\0';
156+ }
157+ /* clear window */
158+ if(w->win->data < 0)
159+ w->win->data = winopenfile(w->win, "data");
160+ if(winsetaddr(w->win, ",", 0))
161+ write(w->win->data, "", 0);
162+
163+ if(!normal)
164+ Bprint(w->win->body, "%s\n\n", p);
165+
166+ while(p = Brdline(bin, '\n')){
167+ p[Blinelen(bin)-1] = '\0';
168+ if(normal)
169+ Bprint(w->win->body, "%s\n", p);
170+ else{
171+ if(p[0]=='D')
172+ w->time = strtoul(p+1, 0, 10);
173+ else if(p[0]=='#')
174+ Bprint(w->win->body, "%s\n", p+1);
175+ }
176+ }
177+ winclean(w->win);
178+ free(bin);
179+ close(fd);
180+}
181+
182+static int
183+iscmd(char *s, char *cmd)
184+{
185+ int len;
186+
187+ len = strlen(cmd);
188+ return strncmp(s, cmd, len)==0 && (s[len]=='\0' || s[len]==' ' || s[len]=='\t' || s[len]=='\n');
189+}
190+
191+static char*
192+skip(char *s, char *cmd)
193+{
194+ s += strlen(cmd);
195+ while(*s==' ' || *s=='\t' || *s=='\n')
196+ s++;
197+ return s;
198+}
199+
200+int
201+wikiload(Wiki *w, char *arg)
202+{
203+ char *p, *q, *path, *addr;
204+ int rv;
205+
206+ p = nil;
207+ if(arg[0] == '/')
208+ path = arg;
209+ else{
210+ p = emalloc(strlen(w->arg)+1+strlen(arg)+1);
211+ strcpy(p, w->arg);
212+ if(q = strrchr(p, '/')){
213+ ++q;
214+ *q = '\0';
215+ }else
216+ *p = '\0';
217+ strcat(p, arg);
218+ cleanname(p);
219+ path = p;
220+ }
221+ if(addr=strchr(path, ':'))
222+ *addr++ = '\0';
223+
224+ rv = wikiopen(path, addr)==0;
225+ free(p);
226+ if(rv)
227+ return 1;
228+ return wikiopen(arg, 0)==0;
229+}
230+
231+/* return 1 if handled, 0 otherwise */
232+int
233+wikicmd(Wiki *w, char *s)
234+{
235+ char *p;
236+ s = skip(s, "");
237+
238+ if(iscmd(s, "Del")){
239+ if(windel(w->win, 0))
240+ w->dead = 1;
241+ return 1;
242+ }
243+ if(iscmd(s, "New")){
244+ wikinew(skip(s, "New"));
245+ return 1;
246+ }
247+ if(iscmd(s, "History"))
248+ return wikiload(w, "history.txt");
249+ if(iscmd(s, "Diff"))
250+ return wikidiff(w);
251+ if(iscmd(s, "Get")){
252+ if(winisdirty(w->win) && !w->win->warned){
253+ w->win->warned = 1;
254+ fprint(2, "%s/%s modified\n", dir, w->arg);
255+ }else{
256+ w->win->warned = 0;
257+ wikiget(w);
258+ }
259+ return 1;
260+ }
261+ if(iscmd(s, "Put")){
262+ if((p=strchr(w->arg, '/')) && p[1]!='\0')
263+ fprint(2, "%s/%s is read-only\n", dir, w->arg);
264+ else
265+ wikiput(w);
266+ return 1;
267+ }
268+ return 0;
269+}
270+
271+/* need to expand selection more than default word */
272+static long
273+eval(Window *w, char *s, ...)
274+{
275+ char buf[64];
276+ va_list arg;
277+
278+ va_start(arg, s);
279+ vsnprint(buf, sizeof buf, s, arg);
280+ va_end(arg);
281+
282+ if(winsetaddr(w, buf, 1)==0)
283+ return -1;
284+
285+ if(pread(w->addr, buf, 24, 0) != 24)
286+ return -1;
287+ return strtol(buf, 0, 10);
288+}
289+
290+static int
291+getdot(Window *w, long *q0, long *q1)
292+{
293+ char buf[24];
294+
295+ ctlprint(w->ctl, "addr=dot\n");
296+ if(pread(w->addr, buf, 24, 0) != 24)
297+ return -1;
298+ *q0 = atoi(buf);
299+ *q1 = atoi(buf+12);
300+ return 0;
301+}
302+
303+static Event*
304+expand(Window *w, Event *e, Event *eacme)
305+{
306+ long q0, q1, x;
307+
308+ if(getdot(w, &q0, &q1)==0 && q0 <= e->q0 && e->q0 <= q1){
309+ e->q0 = q0;
310+ e->q1 = q1;
311+ return e;
312+ }
313+
314+ q0 = eval(w, "#%lud-/\\[/", e->q0);
315+ if(q0 < 0)
316+ return eacme;
317+ if(eval(w, "#%lud+/\\]/", q0) < e->q0) /* [ closes before us */
318+ return eacme;
319+ q1 = eval(w, "#%lud+/\\]/", e->q1);
320+ if(q1 < 0)
321+ return eacme;
322+ if((x=eval(w, "#%lud-/\\[/", q1))==-1 || x > e->q1) /* ] opens after us */
323+ return eacme;
324+ e->q0 = q0+1;
325+ e->q1 = q1;
326+ return e;
327+}
328+
329+void
330+acmeevent(Wiki *wiki, Event *e)
331+{
332+ Event *ea, *e2, *eq;
333+ Window *w;
334+ char *s, *t, *buf;
335+ int na;
336+
337+ w = wiki->win;
338+ switch(e->c1){ /* origin of action */
339+ default:
340+ Unknown:
341+ fprint(2, "unknown message %c%c\n", e->c1, e->c2);
342+ break;
343+
344+ case 'F': /* generated by our actions; ignore */
345+ break;
346+
347+ case 'E': /* write to body or tag; can't affect us */
348+ break;
349+
350+ case 'K': /* type away; we don't care */
351+ if(e->c2 == 'I' || e->c2 == 'D')
352+ w->warned = 0;
353+ break;
354+
355+ case 'M': /* mouse event */
356+ switch(e->c2){ /* type of action */
357+ case 'x': /* mouse: button 2 in tag */
358+ case 'X': /* mouse: button 2 in body */
359+ ea = nil;
360+ //e2 = nil;
361+ s = e->b;
362+ if(e->flag & 2){ /* null string with non-null expansion */
363+ e2 = recvp(w->cevent);
364+ if(e->nb==0)
365+ s = e2->b;
366+ }
367+ if(e->flag & 8){ /* chorded argument */
368+ ea = recvp(w->cevent); /* argument */
369+ na = ea->nb;
370+ recvp(w->cevent); /* ignore origin */
371+ }else
372+ na = 0;
373+
374+ /* append chorded arguments */
375+ if(na){
376+ t = emalloc(strlen(s)+1+na+1);
377+ sprint(t, "%s %s", s, ea->b);
378+ s = t;
379+ }
380+ /* if it's a known command, do it */
381+ /* if it's a long message, it can't be for us anyway */
382+ // DPRINT(2, "exec: %s\n", s);
383+ if(!wikicmd(wiki, s)) /* send it back */
384+ winwriteevent(w, e);
385+ if(na)
386+ free(s);
387+ break;
388+
389+ case 'l': /* mouse: button 3 in tag */
390+ case 'L': /* mouse: button 3 in body */
391+ //buf = nil;
392+ eq = e;
393+ if(e->flag & 2){ /* we do our own expansion for loads */
394+ e2 = recvp(w->cevent);
395+ eq = expand(w, eq, e2);
396+ }
397+ s = eq->b;
398+ if(eq->q1>eq->q0 && eq->nb==0){
399+ buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
400+ winread(w, eq->q0, eq->q1, buf);
401+ s = buf;
402+ }
403+ if(!wikiload(wiki, s))
404+ winwriteevent(w, e);
405+ break;
406+
407+ case 'i': /* mouse: text inserted in tag */
408+ case 'd': /* mouse: text deleted from tag */
409+ break;
410+
411+ case 'I': /* mouse: text inserted in body */
412+ case 'D': /* mouse: text deleted from body */
413+ w->warned = 0;
414+ break;
415+
416+ default:
417+ goto Unknown;
418+ }
419+ }
420+}
421+
422+void
423+wikithread(void *v)
424+{
425+ char tmp[40];
426+ Event *e;
427+ Wiki *w;
428+
429+ w = v;
430+
431+ if(w->isnew){
432+ sprint(tmp, "+new+%d", w->isnew);
433+ wikiname(w->win, tmp);
434+ if(w->arg){
435+ winopenbody(w->win, OWRITE);
436+ Bprint(w->win->body, "%s\n\n", w->arg);
437+ }
438+ winclean(w->win);
439+ }else if(!w->special){
440+ wikiget(w);
441+ wikiname(w->win, w->arg);
442+ if(w->addr)
443+ winselect(w->win, w->addr, 1);
444+ }
445+ fprint(w->win->ctl, "menu\n");
446+ wintagwrite(w->win, "Get History Diff New", 4+8+4+4);
447+ winclean(w->win);
448+
449+ while(!w->dead && (e = recvp(w->win->cevent)))
450+ acmeevent(w, e);
451+
452+ windormant(w->win);
453+ unlink(w);
454+ free(w->win);
455+ free(w->arg);
456+ free(w);
457+ threadexits(nil);
458+}
459+
460+int
461+wikiopen(char *arg, char *addr)
462+{
463+ Dir *d;
464+ char *p;
465+ Wiki *w;
466+
467+/*
468+ if(arg==nil){
469+ if(write(mapfd, title, strlen(title)) < 0
470+ || seek(mapfd, 0, 0) < 0 || (n=read(mapfd, tmp, sizeof(tmp)-2)) < 0){
471+ fprint(2, "Wiki: no page '%s' found: %r\n", title);
472+ return -1;
473+ }
474+ if(tmp[n-1] == '\n')
475+ tmp[--n] = '\0';
476+ tmp[n++] = '/';
477+ tmp[n] = '\0';
478+ arg = tmp;
479+ }
480+*/
481+
482+ /* replace embedded '\n' in links by ' ' */
483+ for(p=arg; *p; p++)
484+ if(*p=='\n')
485+ *p = ' ';
486+
487+ if(strncmp(arg, dir, strlen(dir))==0 && arg[strlen(dir)]=='/' && arg[strlen(dir)+1])
488+ arg += strlen(dir)+1;
489+ else if(arg[0] == '/')
490+ return -1;
491+
492+ if((d = dirstat(arg)) == nil)
493+ return -1;
494+
495+ if((d->mode&DMDIR) && arg[strlen(arg)-1] != '/'){
496+ p = emalloc(strlen(arg)+2);
497+ strcpy(p, arg);
498+ strcat(p, "/");
499+ arg = p;
500+ }else if(!(d->mode&DMDIR) && arg[strlen(arg)-1]=='/'){
501+ arg = estrdup(arg);
502+ arg[strlen(arg)-1] = '\0';
503+ }else
504+ arg = estrdup(arg);
505+ free(d);
506+
507+ /* rewrite /current into / */
508+ if(strlen(arg) > 8 && strcmp(arg+strlen(arg)-8, "/current")==0)
509+ arg[strlen(arg)-8+1] = '\0';
510+
511+ /* look for window already open */
512+ for(w=wlist; w; w=w->next){
513+ if(strcmp(w->arg, arg)==0){
514+ ctlprint(w->win->ctl, "show\n");
515+ return 0;
516+ }
517+ }
518+
519+ w = emalloc(sizeof *w);
520+ w->arg = arg;
521+ w->addr = addr;
522+ w->win = newwindow();
523+ link(w);
524+
525+ proccreate(wineventproc, w->win, STACK);
526+ threadcreate(wikithread, w, STACK);
527+ return 0;
528+}
529+
530+void
531+wikinew(char *arg)
532+{
533+ static int n;
534+ Wiki *w;
535+
536+ w = emalloc(sizeof *w);
537+ if(arg)
538+ arg = estrdup(arg);
539+ w->arg = arg;
540+ w->win = newwindow();
541+ w->isnew = ++n;
542+ proccreate(wineventproc, w->win, STACK);
543+ threadcreate(wikithread, w, STACK);
544+}
545+
546+typedef struct Diffarg Diffarg;
547+struct Diffarg {
548+ Wiki *w;
549+ char *dir;
550+};
551+
552+void
553+execdiff(void *v)
554+{
555+ char buf[64];
556+ Diffarg *a;
557+
558+ a = v;
559+
560+ rfork(RFFDG);
561+ close(0);
562+ open("/dev/null", OREAD);
563+ sprint(buf, "/mnt/wsys/%d/body", a->w->win->id);
564+ close(1);
565+ open(buf, OWRITE);
566+ close(2);
567+ open(buf, OWRITE);
568+ sprint(buf, "/mnt/wsys/%d", a->w->win->id);
569+ bind(buf, "/dev", MBEFORE);
570+
571+ procexecl(nil, "/acme/wiki/wiki.diff", "wiki.diff", a->dir, nil);
572+}
573+
574+int
575+wikidiff(Wiki *w)
576+{
577+ Diffarg *d;
578+ char *p, *q, *r;
579+ Wiki *nw;
580+
581+ p = emalloc(strlen(w->arg)+10);
582+ strcpy(p, w->arg);
583+ if(q = strchr(p, '/'))
584+ *q = '\0';
585+ r = estrdup(p);
586+ strcat(p, "/+Diff");
587+
588+ nw = emalloc(sizeof *w);
589+ nw->arg = p;
590+ nw->win = newwindow();
591+ nw->special = 1;
592+
593+ d = emalloc(sizeof(*d));
594+ d->w = nw;
595+ d->dir = r;
596+ wikiname(nw->win, p);
597+ proccreate(wineventproc, nw->win, STACK);
598+ proccreate(execdiff, d, STACK);
599+ threadcreate(wikithread, nw, STACK);
600+ return 1;
601+}
602+
acme/wiki/src/win.6+0−0

Binary file not shown.

acme/wiki/src/win.8+0−0

Binary file not shown.

acme/wiki/src/win.c+341−0
@@ -0,0 +1,341 @@
1+#include "awiki.h"
2+
3+Window*
4+newwindow(void)
5+{
6+ char buf[12];
7+ Window *w;
8+
9+ w = emalloc(sizeof(Window));
10+ w->ctl = open("/mnt/wsys/new/ctl", ORDWR|OCEXEC);
11+ if(w->ctl<0 || read(w->ctl, buf, 12)!=12)
12+ error("can't open window ctl file: %r");
13+ ctlprint(w->ctl, "noscroll\n");
14+ w->id = atoi(buf);
15+ w->event = winopenfile(w, "event");
16+ w->addr = -1; /* will be opened when needed */
17+ w->body = nil;
18+ w->data = -1;
19+ w->cevent = chancreate(sizeof(Event*), 0);
20+ if(w->cevent == nil)
21+ error("cevent is nil: %r");
22+ return w;
23+}
24+
25+void
26+winsetdump(Window *w, char *dir, char *cmd)
27+{
28+ if(dir != nil)
29+ ctlprint(w->ctl, "dumpdir %s\n", dir);
30+ if(cmd != nil)
31+ ctlprint(w->ctl, "dump %s\n", cmd);
32+}
33+
34+void
35+wineventproc(void *v)
36+{
37+ Window *w;
38+ int i;
39+
40+ threadsetname("wineventproc");
41+ w = v;
42+ for(i=0; ; i++){
43+ if(i >= NEVENT)
44+ i = 0;
45+ wingetevent(w, &w->e[i]);
46+ sendp(w->cevent, &w->e[i]);
47+ }
48+}
49+
50+int
51+winopenfile(Window *w, char *f)
52+{
53+ char buf[64];
54+ int fd;
55+
56+ sprint(buf, "/mnt/wsys/%d/%s", w->id, f);
57+ fd = open(buf, ORDWR|OCEXEC);
58+ if(fd < 0)
59+ error("can't open window file %s: %r", f);
60+ return fd;
61+}
62+
63+void
64+wintagwrite(Window *w, char *s, int n)
65+{
66+ int fd;
67+
68+ fd = winopenfile(w, "tag");
69+ if(write(fd, s, n) != n)
70+ error("tag write: %r");
71+ close(fd);
72+}
73+
74+void
75+winname(Window *w, char *s)
76+{
77+ ctlprint(w->ctl, "name %s\n", s);
78+}
79+
80+void
81+winopenbody(Window *w, int mode)
82+{
83+ char buf[256];
84+
85+ sprint(buf, "/mnt/wsys/%d/body", w->id);
86+ w->body = Bopen(buf, mode|OCEXEC);
87+ if(w->body == nil)
88+ error("can't open window body file: %r");
89+}
90+
91+void
92+winclosebody(Window *w)
93+{
94+ if(w->body != nil){
95+ Bterm(w->body);
96+ w->body = nil;
97+ }
98+}
99+
100+void
101+winwritebody(Window *w, char *s, int n)
102+{
103+ if(w->body == nil)
104+ winopenbody(w, OWRITE);
105+ if(Bwrite(w->body, s, n) != n)
106+ error("write error to window: %r");
107+}
108+
109+int
110+wingetec(Window *w)
111+{
112+ if(w->nbuf == 0){
113+ w->nbuf = read(w->event, w->buf, sizeof w->buf);
114+ if(w->nbuf <= 0){
115+ /* probably because window has exited, and only called by wineventproc, so just shut down */
116+ threadexits(nil);
117+ }
118+ w->bufp = w->buf;
119+ }
120+ w->nbuf--;
121+ return *w->bufp++;
122+}
123+
124+int
125+wingeten(Window *w)
126+{
127+ int n, c;
128+
129+ n = 0;
130+ while('0'<=(c=wingetec(w)) && c<='9')
131+ n = n*10+(c-'0');
132+ if(c != ' ')
133+ error("event number syntax");
134+ return n;
135+}
136+
137+int
138+wingeter(Window *w, char *buf, int *nb)
139+{
140+ Rune r;
141+ int n;
142+
143+ r = wingetec(w);
144+ buf[0] = r;
145+ n = 1;
146+ if(r >= Runeself) {
147+ while(!fullrune(buf, n))
148+ buf[n++] = wingetec(w);
149+ chartorune(&r, buf);
150+ }
151+ *nb = n;
152+ return r;
153+}
154+
155+void
156+wingetevent(Window *w, Event *e)
157+{
158+ int i, nb;
159+
160+ e->c1 = wingetec(w);
161+ e->c2 = wingetec(w);
162+ e->q0 = wingeten(w);
163+ e->q1 = wingeten(w);
164+ e->flag = wingeten(w);
165+ e->nr = wingeten(w);
166+ if(e->nr > EVENTSIZE)
167+ error("event string too long");
168+ e->nb = 0;
169+ for(i=0; i<e->nr; i++){
170+ e->r[i] = wingeter(w, e->b+e->nb, &nb);
171+ e->nb += nb;
172+ }
173+ e->r[e->nr] = 0;
174+ e->b[e->nb] = 0;
175+ if(wingetec(w) != '\n')
176+ error("event syntax error");
177+}
178+
179+void
180+winwriteevent(Window *w, Event *e)
181+{
182+ fprint(w->event, "%c%c%d %d\n", e->c1, e->c2, e->q0, e->q1);
183+}
184+
185+static int
186+nrunes(char *s, int nb)
187+{
188+ int i, n;
189+ Rune r;
190+
191+ n = 0;
192+ for(i=0; i<nb; n++)
193+ i += chartorune(&r, s+i);
194+ return n;
195+}
196+
197+void
198+winread(Window *w, uint q0, uint q1, char *data)
199+{
200+ int m, n, nr;
201+ char buf[256];
202+
203+ if(w->addr < 0)
204+ w->addr = winopenfile(w, "addr");
205+ if(w->data < 0)
206+ w->data = winopenfile(w, "data");
207+ m = q0;
208+ while(m < q1){
209+ n = sprint(buf, "#%d", m);
210+ if(write(w->addr, buf, n) != n)
211+ error("error writing addr: %r");
212+ n = read(w->data, buf, sizeof buf);
213+ if(n <= 0)
214+ error("reading data: %r");
215+ nr = nrunes(buf, n);
216+ while(m+nr >q1){
217+ do; while(n>0 && (buf[--n]&0xC0)==0x80);
218+ --nr;
219+ }
220+ if(n == 0)
221+ break;
222+ memmove(data, buf, n);
223+ data += n;
224+ *data = 0;
225+ m += nr;
226+ }
227+}
228+
229+void
230+windormant(Window *w)
231+{
232+ if(w->addr >= 0){
233+ close(w->addr);
234+ w->addr = -1;
235+ }
236+ if(w->body != nil){
237+ Bterm(w->body);
238+ w->body = nil;
239+ }
240+ if(w->data >= 0){
241+ close(w->data);
242+ w->data = -1;
243+ }
244+}
245+
246+
247+int
248+windel(Window *w, int sure)
249+{
250+ if(sure)
251+ write(w->ctl, "delete\n", 7);
252+ else if(write(w->ctl, "del\n", 4) != 4)
253+ return 0;
254+ /* event proc will die due to read error from event file */
255+ windormant(w);
256+ close(w->ctl);
257+ w->ctl = -1;
258+ close(w->event);
259+ w->event = -1;
260+ return 1;
261+}
262+
263+void
264+winclean(Window *w)
265+{
266+ if(w->body)
267+ Bflush(w->body);
268+ ctlprint(w->ctl, "clean\n");
269+}
270+
271+int
272+winisdirty(Window *w)
273+{
274+ char m;
275+
276+ if (seek(w->ctl, 4*(11+1) + 10, 0) < 0)
277+ error("control file seek error: %r");
278+
279+ if(read(w->ctl, &m, 1) != 1)
280+ error("control file read error: %r");
281+
282+ if (m == '0')
283+ return 0;
284+ else if (m == '1')
285+ return 1;
286+ else
287+ error("can't parse ismodified field: %c", m);
288+ return 1; // better safe than sorry
289+
290+}
291+
292+int
293+winsetaddr(Window *w, char *addr, int errok)
294+{
295+ if(w->addr < 0)
296+ w->addr = winopenfile(w, "addr");
297+ if(write(w->addr, addr, strlen(addr)) < 0){
298+ if(!errok)
299+ error("error writing addr(%s): %r", addr);
300+ return 0;
301+ }
302+ return 1;
303+}
304+
305+int
306+winselect(Window *w, char *addr, int errok)
307+{
308+ if(winsetaddr(w, addr, errok)){
309+ ctlprint(w->ctl, "dot=addr\n");
310+ return 1;
311+ }
312+ return 0;
313+}
314+
315+char*
316+winreadbody(Window *w, int *np) /* can't use readfile because acme doesn't report the length */
317+{
318+ char *s;
319+ int m, na, n;
320+
321+ if(w->body != nil)
322+ winclosebody(w);
323+ winopenbody(w, OREAD);
324+ s = nil;
325+ na = 0;
326+ n = 0;
327+ for(;;){
328+ if(na < n+512){
329+ na += 1024;
330+ s = realloc(s, na+1);
331+ }
332+ m = Bread(w->body, s+n, na-n);
333+ if(m <= 0)
334+ break;
335+ n += m;
336+ }
337+ s[n] = 0;
338+ winclosebody(w);
339+ *np = n;
340+ return s;
341+}
acme/wiki/wiki.diff+27−0
@@ -0,0 +1,27 @@
1+#!/bin/rc
2+
3+rfork n
4+cd $1
5+*=(`{ls -drp [0-9]*})
6+
7+while(! ~ $#* 0 1){
8+ diff -n $2/index.txt $1/index.txt | awk -F'[\/ :]' '
9+ $1 ~/^[0-9]+$/ {
10+ getA = "cat "$5"/current | sed -n -e ''1d; /^A/s/^A//p; /^#/q''"
11+ getA | getline A; close getA
12+ $1 = t2d($1)
13+ $5 = t2d($5)
14+ print "\n" A ":\n" $1":"$3" "$4" "$5":"$7
15+ next
16+ }
17+ { print }
18+
19+ function t2d(t) {
20+ c = "date "t; c|getline l; close c
21+ split(l, a, "[ :]+")
22+ return a[1]" "a[2]" "a[3]" "a[4]":"a[5]" "a[8]"("t")"
23+ }'
24+ shift
25+}
26+
27+echo clean >/dev/ctl >[2]/dev/null
sys/games/lib/4scores+0−0

Empty file deleted.

sys/games/lib/5scores+0−0

Empty file deleted.

sys/games/lib/anawords+0−18766
@@ -1,18766 +0,0 @@
1−a
2−aback
3−abacus
4−abaft
5−abandon
6−abase
7−abash
8−abate
9−abattoir
10−abbe
11−abbess
12−abbey
13−abbot
14−abbreviate
15−abc
16−abdicate
17−abdomen
18−abdominal
19−abduct
20−abeam
21−abed
22−aberration
23−abet
24−abeyance
25−abhor
26−abide
27−ability
28−abject
29−abjure
30−ablative
31−ablaut
32−ablaze
33−able
34−ablution
35−abnegation
36−abnormal
37−abo
38−aboard
39−abode
40−abolish
41−abominable
42−abominate
43−aboriginal
44−abort
45−abortion
46−abortive
47−abound
48−about
49−above
50−abracadabra
51−abrade
52−abrasion
53−abrasive
54−abreast
55−abridge
56−abroad
57−abrogate
58−abrupt
59−abscess
60−abscond
61−absence
62−absent
63−absentee
64−absinth
65−absinthe
66−absolute
67−absolution
68−absolve
69−absorb
70−abstain
71−abstemious
72−abstention
73−abstinence
74−abstract
75−abstraction
76−abstruse
77−absurd
78−abundance
79−abundant
80−abuse
81−abusive
82−abut
83−abysm
84−abysmal
85−abyss
86−acacia
87−academic
88−academicals
89−academy
90−accede
91−accelerando
92−accelerate
93−accelerator
94−accent
95−accentuate
96−accept
97−access
98−accessary
99−accession
100−accessory
101−accidence
102−accident
103−accidental
104−acclaim
105−acclamation
106−acclimate
107−acclimatize
108−acclivity
109−accolade
110−accommodate
111−accommodation
112−accompaniment
113−accompany
114−accomplice
115−accomplish
116−accord
117−accordance
118−according
119−accordion
120−accost
121−accouchement
122−account
123−accountancy
124−accountant
125−accoutrements
126−accredit
127−accretion
128−accrue
129−accumulate
130−accumulation
131−accumulator
132−accurate
133−accursed
134−accusation
135−accusative
136−accuse
137−accustom
138−ace
139−acerbity
140−acetic
141−acetylene
142−ache
143−achieve
144−achilles
145−acid
146−acknowledge
147−acme
148−acne
149−acolyte
150−aconite
151−acorn
152−acoustic
153−acquaint
154−acquaintance
155−acquiesce
156−acquire
157−acquisition
158−acquisitive
159−acquit
160−acre
161−acrid
162−acrimony
163−acrobat
164−acronym
165−acropolis
166−across
167−acrostic
168−acrylic
169−act
170−acting
171−actinism
172−action
173−activate
174−active
175−activist
176−activity
177−actor
178−actress
179−actual
180−actuary
181−actuate
182−acuity
183−acumen
184−acupuncture
185−acute
186−ad
187−adage
188−adagio
189−adam
190−adamant
191−adapt
192−add
193−addendum
194−adder
195−addict
196−addition
197−additive
198−addle
199−address
200−adduce
201−adenoids
202−adept
203−adequate
204−adhere
205−adherent
206−adhesion
207−adhesive
208−adieu
209−adipose
210−adjacent
211−adjective
212−adjoin
213−adjourn
214−adjudge
215−adjudicate
216−adjunct
217−adjure
218−adjust
219−adjutant
220−admass
221−administer
222−administration
223−administrative
224−administrator
225−admirable
226−admiral
227−admiration
228−admire
229−admissible
230−admission
231−admit
232−admittance
233−admix
234−admixture
235−admonish
236−ado
237−adobe
238−adolescence
239−adopt
240−adore
241−adorn
242−adrenal
243−adrenalin
244−adrift
245−adroit
246−adulation
247−adult
248−adulterate
249−adultery
250−adumbrate
251−advance
252−advantage
253−advantageous
254−advent
255−adventitious
256−adventure
257−adverb
258−adversary
259−adverse
260−adversity
261−advert
262−advertise
263−advice
264−advisable
265−advise
266−advocate
267−advowson
268−adz
269−adze
270−aegis
271−aeon
272−aerate
273−aerial
274−aerie
275−aerobatics
276−aerodrome
277−aerodynamics
278−aeronaut
279−aeronautics
280−aeroplane
281−aerosol
282−aerospace
283−aertex
284−aery
285−aesthete
286−aesthetic
287−aether
288−aetiology
289−afar
290−affable
291−affair
292−affect
293−affectation
294−affection
295−affectionate
296−affiance
297−affidavit
298−affiliate
299−affiliation
300−affinity
301−affirm
302−affix
303−afflatus
304−afflict
305−affliction
306−affluence
307−affluent
308−afford
309−afforest
310−affranchise
311−affray
312−affront
313−afield
314−afire
315−aflame
316−afloat
317−afoot
318−afore
319−afoul
320−afraid
321−afresh
322−african
323−afrikaans
324−aft
325−after
326−afternoon
327−afters
328−afterwards
329−again
330−against
331−agape
332−agate
333−agave
334−age
335−agency
336−agenda
337−agent
338−agglomerate
339−agglutinate
340−aggrandize
341−aggravate
342−aggregate
343−aggression
344−aggressive
345−aggrieve
346−aggro
347−aghast
348−agile
349−agin
350−agitate
351−aglow
352−agnail
353−agnostic
354−ago
355−agog
356−agony
357−agora
358−agrarian
359−agree
360−agreeable
361−agreement
362−agriculture
363−aground
364−ague
365−ah
366−aha
367−ahead
368−ahem
369−ahoy
370−aid
371−aigret
372−aigrette
373−ail
374−aileron
375−ailment
376−aim
377−air
378−airedale
379−airless
380−airy
381−aisle
382−aitch
383−ajar
384−akimbo
385−akin
386−alabaster
387−alack
388−alacrity
389−alarm
390−alas
391−alb
392−albatross
393−albeit
394−albino
395−album
396−albumen
397−alchemist
398−alchemy
399−alcohol
400−alcove
401−alder
402−alderman
403−ale
404−alee
405−alert
406−alexandrine
407−alexia
408−alfalfa
409−alfresco
410−alga
411−algebra
412−alias
413−alibi
414−alien
415−alienate
416−alienist
417−alight
418−align
419−alike
420−alimentary
421−alimony
422−alive
423−alkali
424−all
425−allah
426−allay
427−allege
428−allegiance
429−allegory
430−allegretto
431−allegro
432−alleluia
433−allergy
434−alleviate
435−alley
436−alliance
437−allied
438−alligator
439−alliteration
440−allocate
441−allot
442−allow
443−allowance
444−alloy
445−allspice
446−allude
447−allure
448−allusion
449−alluvial
450−ally
451−almanac
452−almighty
453−almond
454−almoner
455−almost
456−alms
457−aloe
458−aloft
459−alone
460−along
461−aloof
462−aloud
463−alp
464−alpaca
465−alpenstock
466−alpha
467−alphabet
468−alpine
469−already
470−alright
471−alsatian
472−also
473−altar
474−alter
475−altercation
476−alternate
477−alternative
478−altho
479−although
480−altimeter
481−altitude
482−alto
483−altogether
484−altruism
485−alum
486−aluminium
487−alumna
488−alumnus
489−alveolar
490−always
491−am
492−amah
493−amain
494−amalgam
495−amalgamate
496−amanuensis
497−amaryllis
498−amass
499−amateur
500−amatory
501−amaze
502−amazon
503−ambassador
504−amber
505−ambergris
506−ambidextrous
507−ambience
508−ambient
509−ambiguity
510−ambiguous
511−ambit
512−ambition
513−ambitious
514−ambivalent
515−amble
516−ambrosia
517−ambulance
518−ambuscade
519−ambush
520−ameba
521−ameer
522−ameliorate
523−amen
524−amenable
525−amend
526−amends
527−amenity
528−america
529−american
530−amethyst
531−amiable
532−amicable
533−amid
534−amidships
535−amir
536−amiss
537−amity
538−ammeter
539−ammonia
540−ammonite
541−ammunition
542−amnesia
543−amnesty
544−amoeba
545−amok
546−among
547−amoral
548−amorous
549−amorphous
550−amortize
551−amount
552−amour
553−amp
554−ampere
555−amphetamine
556−amphibian
557−amphibious
558−amphitheatre
559−amphora
560−ample
561−amplify
562−amplitude
563−ampoule
564−amputate
565−amuck
566−amulet
567−amuse
568−an
569−anachronism
570−anaconda
571−anaemia
572−anaesthesia
573−anagram
574−anal
575−analects
576−analgesia
577−analogous
578−analogue
579−analogy
580−analyse
581−analysis
582−analyst
583−analyze
584−anapaest
585−anarchy
586−anathema
587−anatomy
588−ancestor
589−anchor
590−anchorite
591−anchovy
592−ancient
593−ancillary
594−and
595−andante
596−andiron
597−anecdote
598−anemia
599−anemic
600−anemometer
601−anemone
602−anent
603−aneroid
604−anew
605−angel
606−angelica
607−angelus
608−anger
609−angle
610−anglican
611−anglicize
612−anglomania
613−anglophile
614−anglophobe
615−anglophobia
616−angora
617−angostura
618−angry
619−angst
620−anguish
621−angular
622−aniline
623−animadvert
624−animal
625−animate
626−animism
627−animosity
628−animus
629−anise
630−ankle
631−anna
632−annals
633−anneal
634−annex
635−annihilate
636−anniversary
637−annotate
638−announce
639−annoy
640−annual
641−annuity
642−annul
643−annular
644−annunciate
645−annunciation
646−anode
647−anodyne
648−anoint
649−anomalous
650−anon
651−anonymity
652−anonymous
653−anopheles
654−anorak
655−another
656−answer
657−ant
658−antagonism
659−antagonist
660−antagonistic
661−antagonize
662−antarctic
663−ante
664−antecedent
665−antechamber
666−antedate
667−antediluvian
668−antelope
669−antenatal
670−antenna
671−antenuptial
672−antepenultimate
673−anterior
674−anteroom
675−anthem
676−anther
677−anthology
678−anthracite
679−anthrax
680−anthropoid
681−anthropology
682−antibiotic
683−antibody
684−antic
685−anticipate
686−anticipation
687−anticyclone
688−antidote
689−antifreeze
690−antiknock
691−antilogarithm
692−antimacassar
693−antimony
694−antipathy
695−antipodes
696−antiquarian
697−antiquary
698−antiquated
699−antique
700−antiquity
701−antirrhinum
702−antiseptic
703−antisocial
704−antitank
705−antithesis
706−antitoxin
707−antitrade
708−antler
709−antonym
710−anus
711−anvil
712−anxiety
713−anxious
714−any
715−anybody
716−anyhow
717−anyone
718−anyplace
719−anything
720−anyway
721−anywhere
722−aorta
723−apace
724−apache
725−apanage
726−apart
727−apartheid
728−apartment
729−apathy
730−ape
731−aperient
732−aperitif
733−aperture
734−apex
735−aphasia
736−aphid
737−aphis
738−aphorism
739−aphrodisiac
740−apiary
741−apiece
742−apish
743−aplomb
744−apocalypse
745−apocrypha
746−apogee
747−apologetic
748−apologize
749−apology
750−apophthegm
751−apoplexy
752−apostasy
753−apostle
754−apostrophe
755−apothecary
756−apothegm
757−apotheosis
758−appal
759−appanage
760−apparatus
761−apparel
762−apparent
763−apparition
764−appeal
765−appear
766−appearance
767−appease
768−appellant
769−appellation
770−append
771−appendage
772−appendix
773−appertain
774−appetite
775−applaud
776−applause
777−apple
778−appliance
779−applicable
780−applicant
781−application
782−applied
783−applique
784−apply
785−appoint
786−appointment
787−apportion
788−apposite
789−apposition
790−appraise
791−appreciable
792−appreciate
793−appreciation
794−apprehend
795−apprehension
796−apprehensive
797−apprentice
798−apprise
799−appro
800−approach
801−approbation
802−appropriate
803−approval
804−approve
805−approximate
806−appurtenance
807−apricot
808−april
809−apron
810−apropos
811−apse
812−apt
813−aptitude
814−aqualung
815−aquamarine
816−aquanaut
817−aquaplane
818−aquarium
819−aquarius
820−aquatic
821−aquatint
822−aquavit
823−aqueduct
824−aqueous
825−aquiline
826−arab
827−arabesque
828−arabian
829−arabic
830−arabist
831−arable
832−arachnid
833−arbiter
834−arbitrament
835−arbitrary
836−arbitrate
837−arbitration
838−arbitrator
839−arbor
840−arboreal
841−arbour
842−arc
843−arcade
844−arcadian
845−arcane
846−arch
847−archaeology
848−archaic
849−archangel
850−archbishop
851−archdeacon
852−archdiocese
853−archduke
854−archer
855−archetype
856−archimandrite
857−archipelago
858−architect
859−architecture
860−archives
861−archway
862−arctic
863−ardent
864−ardour
865−arduous
866−are
867−area
868−areca
869−arena
870−arete
871−argent
872−argon
873−argonaut
874−argosy
875−argot
876−argue
877−argument
878−argumentation
879−argus
880−aria
881−arid
882−aries
883−aright
884−arise
885−aristocracy
886−aristocrat
887−arithmetic
888−ark
889−arm
890−armada
891−armadillo
892−armageddon
893−armament
894−armature
895−armistice
896−armoire
897−armor
898−armorial
899−armour
900−arms
901−army
902−arnica
903−aroma
904−arose
905−around
906−arouse
907−arpeggio
908−arquebus
909−arrack
910−arraign
911−arrange
912−arrangement
913−arrant
914−arras
915−array
916−arrears
917−arrest
918−arrival
919−arrive
920−arrogant
921−arrogate
922−arrow
923−arrowroot
924−arse
925−arsenal
926−arsenic
927−arson
928−art
929−artefact
930−arterial
931−arteriosclerosis
932−artery
933−artesian
934−artful
935−arthritis
936−artichoke
937−article
938−articulate
939−articulation
940−artifact
941−artifice
942−artificer
943−artificial
944−artillery
945−artisan
946−artist
947−artiste
948−artistic
949−artistry
950−artless
951−arty
952−arum
953−aryan
954−as
955−asbestos
956−ascend
957−ascendancy
958−ascendant
959−ascension
960−ascent
961−ascertain
962−ascetic
963−ascorbic
964−ascribe
965−asdic
966−aseptic
967−asexual
968−ash
969−ashamed
970−ashen
971−ashore
972−ashy
973−asian
974−asiatic
975−aside
976−asinine
977−ask
978−askance
979−askew
980−asking
981−aslant
982−asleep
983−asp
984−asparagus
985−aspect
986−aspen
987−asperity
988−asperse
989−asphalt
990−asphodel
991−asphyxia
992−aspic
993−aspidistra
994−aspirant
995−aspirate
996−aspiration
997−aspire
998−aspirin
999−ass
1000−assagai
1001−assail
1002−assassin
1003−assault
1004−assay
1005−assegai
1006−assemblage
1007−assemble
1008−assembly
1009−assent
1010−assert
1011−assertion
1012−assertive
1013−assess
1014−asset
1015−asseverate
1016−assiduity
1017−assiduous
1018−assign
1019−assignation
1020−assimilate
1021−assist
1022−assize
1023−associate
1024−association
1025−assonance
1026−assorted
1027−assuage
1028−assume
1029−assumption
1030−assurance
1031−assure
1032−aster
1033−asterisk
1034−astern
1035−asteroid
1036−asthma
1037−astigmatism
1038−astir
1039−astonish
1040−astound
1041−astrakhan
1042−astral
1043−astray
1044−astride
1045−astringent
1046−astrodome
1047−astrolabe
1048−astrology
1049−astronaut
1050−astronomy
1051−astrophysics
1052−astute
1053−asunder
1054−asylum
1055−at
1056−atabrine
1057−atavism
1058−ate
1059−atelier
1060−atheism
1061−athirst
1062−athlete
1063−athletic
1064−athletics
1065−athwart
1066−atishoo
1067−atlas
1068−atmosphere
1069−atmospheric
1070−atoll
1071−atom
1072−atomic
1073−atomize
1074−atonal
1075−atone
1076−atop
1077−atrabilious
1078−atrocious
1079−atrocity
1080−atrophy
1081−attaboy
1082−attach
1083−attache
1084−attack
1085−attain
1086−attainder
1087−attar
1088−attempt
1089−attend
1090−attendance
1091−attendant
1092−attention
1093−attentive
1094−attenuate
1095−attest
1096−attic
1097−attire
1098−attitude
1099−attorney
1100−attract
1101−attraction
1102−attractive
1103−attribute
1104−attributive
1105−attrition
1106−attune
1107−aubergine
1108−aubrietia
1109−auburn
1110−auction
1111−audacious
1112−audible
1113−audience
1114−audit
1115−audition
1116−auditor
1117−auditorium
1118−auditory
1119−auger
1120−aught
1121−augment
1122−augur
1123−august
1124−augustan
1125−auk
1126−aunt
1127−aura
1128−aural
1129−aureole
1130−auricle
1131−auricular
1132−auriferous
1133−aurora
1134−auspices
1135−auspicious
1136−aussie
1137−austere
1138−autarchy
1139−autarky
1140−authentic
1141−authenticate
1142−author
1143−authoritarian
1144−authoritative
1145−authority
1146−authorize
1147−autism
1148−auto
1149−autobahn
1150−autobiography
1151−autocracy
1152−autocrat
1153−autogiro
1154−autograph
1155−automat
1156−automate
1157−automatic
1158−automation
1159−automaton
1160−automobile
1161−autonomous
1162−autopsy
1163−autostrada
1164−autumn
1165−auxiliary
1166−avail
1167−available
1168−avalanche
1169−avarice
1170−avast
1171−avatar
1172−avaunt
1173−avenge
1174−avenue
1175−aver
1176−average
1177−averse
1178−aversion
1179−avert
1180−aviary
1181−aviation
1182−avid
1183−avocado
1184−avocation
1185−avoid
1186−avoirdupois
1187−avouch
1188−avow
1189−avuncular
1190−await
1191−awake
1192−awaken
1193−award
1194−aware
1195−awash
1196−away
1197−awe
1198−aweigh
1199−awful
1200−awhile
1201−awkward
1202−awl
1203−awning
1204−awoke
1205−awry
1206−ax
1207−axe
1208−axiom
1209−axis
1210−axle
1211−ay
1212−ayah
1213−aye
1214−azalea
1215−azimuth
1216−azure
1217−b
1218−baa
1219−baas
1220−babble
1221−babe
1222−babel
1223−baboo
1224−baboon
1225−babu
1226−baby
1227−baccalaureate
1228−baccarat
1229−bacchanal
1230−baccy
1231−bachelor
1232−bacillus
1233−back
1234−backgammon
1235−backsheesh
1236−backward
1237−bacon
1238−bacterium
1239−bad
1240−bade
1241−badge
1242−badger
1243−badinage
1244−badminton
1245−baffle
1246−bag
1247−bagatelle
1248−baggage
1249−baggy
1250−bagnio
1251−bagpipe
1252−bags
1253−bah
1254−bail
1255−bailey
1256−bailiff
1257−bairn
1258−bait
1259−baize
1260−bake
1261−bakelite
1262−baksheesh
1263−balalaika
1264−balance
1265−balcony
1266−bald
1267−balderdash
1268−baldric
1269−bale
1270−balk
1271−ball
1272−ballad
1273−ballade
1274−ballast
1275−ballerina
1276−ballet
1277−ballistic
1278−ballocks
1279−balloon
1280−ballot
1281−bally
1282−ballyhoo
1283−balm
1284−baloney
1285−balsa
1286−balsam
1287−baluster
1288−balustrade
1289−bambino
1290−bamboo
1291−bamboozle
1292−ban
1293−banal
1294−banana
1295−band
1296−bandage
1297−bandanna
1298−bandbox
1299−bandeau
1300−bandit
1301−bandoleer
1302−bandy
1303−bane
1304−bang
1305−banger
1306−bangle
1307−banian
1308−banish
1309−banister
1310−banjo
1311−bank
1312−bankrupt
1313−banner
1314−bannock
1315−banns
1316−banquet
1317−banshee
1318−bant
1319−bantam
1320−banter
1321−bantu
1322−banyan
1323−baobab
1324−baptism
1325−baptist
1326−baptize
1327−bar
1328−barb
1329−barbarian
1330−barbaric
1331−barbarism
1332−barbarity
1333−barbarize
1334−barbarous
1335−barbecue
1336−barbel
1337−barber
1338−barbican
1339−barbitone
1340−barbiturate
1341−barcarole
1342−bard
1343−bare
1344−bargain
1345−barge
1346−bargee
1347−baritone
1348−barium
1349−bark
1350−barker
1351−barley
1352−barm
1353−barmy
1354−barn
1355−barnacle
1356−barometer
1357−baron
1358−baronet
1359−baroque
1360−barouche
1361−barque
1362−barrack
1363−barracuda
1364−barrage
1365−barred
1366−barrel
1367−barren
1368−barricade
1369−barrier
1370−barring
1371−barrister
1372−barrow
1373−barter
1374−basalt
1375−bascule
1376−base
1377−baseball
1378−basement
1379−bash
1380−bashful
1381−basic
1382−basil
1383−basilica
1384−basilisk
1385−basin
1386−basis
1387−bask
1388−basket
1389−bass
1390−bassinet
1391−bassoon
1392−bast
1393−bastard
1394−baste
1395−bastinado
1396−bastion
1397−bat
1398−batch
1399−bate
1400−bath
1401−bathe
1402−bathing
1403−bathos
1404−bathysphere
1405−batik
1406−batiste
1407−batman
1408−baton
1409−bats
1410−battalion
1411−batten
1412−batter
1413−battery
1414−batting
1415−battle
1416−battledore
1417−battlements
1418−battue
1419−batty
1420−bauble
1421−baulk
1422−bauxite
1423−bawbee
1424−bawd
1425−bawl
1426−bay
1427−bayonet
1428−bayou
1429−bazaar
1430−bazooka
1431−be
1432−beach
1433−beacon
1434−bead
1435−beadle
1436−beady
1437−beagle
1438−beak
1439−beaker
1440−beam
1441−bean
1442−bear
1443−bearable
1444−beard
1445−bearer
1446−bearing
1447−bearish
1448−beast
1449−beat
1450−beaten
1451−beater
1452−beatific
1453−beatify
1454−beatitude
1455−beatnik
1456−beau
1457−beaujolais
1458−beauteous
1459−beautician
1460−beautiful
1461−beauty
1462−beaver
1463−becalmed
1464−because
1465−beck
1466−beckon
1467−become
1468−bed
1469−bedaubed
1470−bedding
1471−bedecked
1472−bedevil
1473−bedewed
1474−bedimmed
1475−bedlam
1476−bedouin
1477−bedraggled
1478−beduin
1479−bee
1480−beech
1481−beef
1482−been
1483−beep
1484−beer
1485−beeswax
1486−beet
1487−beetle
1488−beeves
1489−befall
1490−befit
1491−befogged
1492−before
1493−beforehand
1494−befoul
1495−befriend
1496−beg
1497−begad
1498−began
1499−beget
1500−beggar
1501−begin
1502−begone
1503−begonia
1504−begorra
1505−begot
1506−begotten
1507−begrimed
1508−begrudge
1509−beguile
1510−begum
1511−begun
1512−behalf
1513−behave
1514−behaviour
1515−behead
1516−beheld
1517−behest
1518−behind
1519−behindhand
1520−behold
1521−beholden
1522−behove
1523−beige
1524−being
1525−bejewelled
1526−belabour
1527−belated
1528−belay
1529−belch
1530−beldam
1531−beldame
1532−beleaguer
1533−belfry
1534−belie
1535−belief
1536−believe
1537−belike
1538−belittle
1539−bell
1540−belladonna
1541−belle
1542−bellicose
1543−belligerency
1544−belligerent
1545−bellow
1546−bellows
1547−belly
1548−belong
1549−beloved
1550−below
1551−belt
1552−bemoan
1553−bemused
1554−ben
1555−bench
1556−bend
1557−beneath
1558−benedick
1559−benedictine
1560−benediction
1561−benefaction
1562−benefactor
1563−benefice
1564−beneficence
1565−beneficial
1566−beneficiary
1567−benefit
1568−benevolence
1569−benevolent
1570−benighted
1571−benign
1572−benignant
1573−benignity
1574−benison
1575−bent
1576−benumbed
1577−benzedrine
1578−benzene
1579−benzine
1580−benzol
1581−bequeath
1582−bequest
1583−berate
1584−bereave
1585−bereft
1586−beret
1587−berg
1588−berry
1589−berserk
1590−berth
1591−beryl
1592−beseech
1593−beseem
1594−beset
1595−beshrew
1596−beside
1597−besides
1598−besiege
1599−besmear
1600−besmirch
1601−besom
1602−besotted
1603−besought
1604−bespangled
1605−bespattered
1606−bespeak
1607−best
1608−bestial
1609−bestiary
1610−bestir
1611−bestow
1612−bestrew
1613−bestride
1614−bet
1615−beta
1616−betake
1617−betel
1618−bethel
1619−bethink
1620−betide
1621−betimes
1622−betoken
1623−betook
1624−betray
1625−betroth
1626−better
1627−bettor
1628−between
1629−betwixt
1630−bevel
1631−beverage
1632−bevy
1633−bewail
1634−beware
1635−bewilder
1636−bewitch
1637−bey
1638−beyond
1639−bezique
1640−bhang
1641−bias
1642−bib
1643−bible
1644−bibliography
1645−bibliophile
1646−bibulous
1647−bicameral
1648−bicarbonate
1649−bicentenary
1650−bicentennial
1651−biceps
1652−bicker
1653−bicycle
1654−bid
1655−bide
1656−bidet
1657−biennial
1658−bier
1659−biff
1660−bifocal
1661−bifurcate
1662−big
1663−bigamy
1664−bight
1665−bigot
1666−bijou
1667−bike
1668−bikini
1669−bilabial
1670−bilateral
1671−bilberry
1672−bile
1673−bilge
1674−bilharzia
1675−bilingual
1676−bilious
1677−bilk
1678−bill
1679−billet
1680−billhook
1681−billiards
1682−billingsgate
1683−billion
1684−billow
1685−billy
1686−biltong
1687−bimetallism
1688−bin
1689−binary
1690−bind
1691−bindweed
1692−bine
1693−binge
1694−bingo
1695−binnacle
1696−binoculars
1697−binomial
1698−biochemistry
1699−biodegradable
1700−biograph
1701−biography
1702−biology
1703−bioscope
1704−bipartisan
1705−biped
1706−biplane
1707−birch
1708−bird
1709−biretta
1710−biro
1711−birth
1712−biscuit
1713−bisect
1714−bisexual
1715−bishop
1716−bismuth
1717−bison
1718−bistro
1719−bit
1720−bitch
1721−bite
1722−bitten
1723−bitter
1724−bittern
1725−bitumen
1726−bivalve
1727−bivouac
1728−biz
1729−bizarre
1730−bizonal
1731−blab
1732−blabber
1733−black
1734−blackamoor
1735−blacken
1736−blacking
1737−bladder
1738−blade
1739−blaeberry
1740−blah
1741−blame
1742−blanch
1743−blancmange
1744−bland
1745−blandishment
1746−blank
1747−blanket
1748−blare
1749−blarney
1750−blase
1751−blaspheme
1752−blast
1753−blatant
1754−blather
1755−blaze
1756−blazer
1757−blazon
1758−bleach
1759−bleachers
1760−bleak
1761−bleary
1762−bleat
1763−bleed
1764−bleep
1765−blemish
1766−blench
1767−blend
1768−blent
1769−bless
1770−blether
1771−blew
1772−blight
1773−blighty
1774−blimey
1775−blimp
1776−blind
1777−blindfold
1778−blink
1779−blinkers
1780−blip
1781−bliss
1782−blister
1783−blithe
1784−blithering
1785−blithesome
1786−blitz
1787−blizzard
1788−bloated
1789−bloater
1790−blob
1791−bloc
1792−block
1793−blockade
1794−blockage
1795−blockhead
1796−blockhouse
1797−bloke
1798−blond
1799−blonde
1800−blood
1801−bloody
1802−bloom
1803−bloomer
1804−bloomers
1805−blossom
1806−blot
1807−blotch
1808−blotto
1809−blouse
1810−blow
1811−blower
1812−blown
1813−blowzy
1814−blubber
1815−bludgeon
1816−blue
1817−bluff
1818−blunder
1819−blunderbuss
1820−blunt
1821−blur
1822−blurb
1823−blurt
1824−blush
1825−bluster
1826−boa
1827−boar
1828−board
1829−boast
1830−boat
1831−boater
1832−boatswain
1833−bob
1834−bobbin
1835−bobby
1836−bobolink
1837−bobsled
1838−bobsleigh
1839−bobtail
1840−boche
1841−bode
1842−bodice
1843−bodily
1844−bodkin
1845−body
1846−boer
1847−boffin
1848−bog
1849−bogey
1850−boggle
1851−bogie
1852−bogus
1853−bogy
1854−bohemian
1855−boil
1856−boiler
1857−boisterous
1858−bold
1859−bole
1860−bolero
1861−boll
1862−bollard
1863−bollocks
1864−boloney
1865−bolshevik
1866−bolshy
1867−bolster
1868−bolt
1869−bomb
1870−bombard
1871−bombardier
1872−bombast
1873−bonanza
1874−bonbon
1875−bond
1876−bondage
1877−bone
1878−boner
1879−bonfire
1880−bongo
1881−bonhomie
1882−bonito
1883−bonkers
1884−bonnet
1885−bonny
1886−bonus
1887−bony
1888−boo
1889−boob
1890−booby
1891−boogie
1892−book
1893−bookie
1894−bookish
1895−booklet
1896−boom
1897−boomerang
1898−boon
1899−boor
1900−boost
1901−boot
1902−bootee
1903−booth
1904−bootleg
1905−bootless
1906−booty
1907−booze
1908−bopeep
1909−boracic
1910−borage
1911−borax
1912−bordeaux
1913−border
1914−bore
1915−boric
1916−born
1917−borne
1918−boron
1919−borough
1920−borrow
1921−borsch
1922−borstal
1923−bortsch
1924−borzoi
1925−bosh
1926−bosky
1927−bosom
1928−boss
1929−botany
1930−botch
1931−both
1932−bother
1933−bottle
1934−bottom
1935−botulism
1936−boudoir
1937−bougainvillea
1938−bough
1939−bought
1940−bouillon
1941−boulder
1942−boulevard
1943−bounce
1944−bound
1945−boundary
1946−bounden
1947−bounder
1948−boundless
1949−bounteous
1950−bountiful
1951−bounty
1952−bouquet
1953−bourbon
1954−bourgeois
1955−bourn
1956−bourse
1957−bout
1958−boutique
1959−bovine
1960−bovril
1961−bow
1962−bowdlerize
1963−bowel
1964−bower
1965−bowl
1966−bowler
1967−bowline
1968−bowls
1969−bowman
1970−bowsprit
1971−box
1972−boy
1973−boycott
1974−bra
1975−brace
1976−bracelet
1977−bracken
1978−bracket
1979−brackish
1980−bract
1981−brad
1982−bradawl
1983−brae
1984−brag
1985−brahmin
1986−braid
1987−braille
1988−brain
1989−braise
1990−brake
1991−bramble
1992−bran
1993−branch
1994−brand
1995−brandish
1996−brandy
1997−brash
1998−brass
1999−brassard
2000−brasserie
2001−brassiere
2002−brat
2003−bravado
2004−brave
2005−bravo
2006−brawl
2007−brawn
2008−bray
2009−braze
2010−brazen
2011−brazier
2012−breach
2013−bread
2014−breadth
2015−break
2016−breakable
2017−breakage
2018−breaker
2019−breakfast
2020−breakneck
2021−breakwater
2022−bream
2023−breast
2024−breath
2025−breathe
2026−breech
2027−breeches
2028−breed
2029−breeze
2030−bren
2031−brethren
2032−breve
2033−brevet
2034−breviary
2035−brevity
2036−brew
2037−briar
2038−bribe
2039−brick
2040−bridal
2041−bride
2042−bridegroom
2043−bridesmaid
2044−bridge
2045−bridle
2046−brief
2047−briefs
2048−brier
2049−brig
2050−brigade
2051−brigand
2052−brigantine
2053−bright
2054−brill
2055−brilliant
2056−brilliantine
2057−brim
2058−brimstone
2059−brindled
2060−brine
2061−bring
2062−brink
2063−briny
2064−brioche
2065−briquet
2066−briquette
2067−brisk
2068−brisket
2069−bristle
2070−britain
2071−british
2072−briton
2073−brittle
2074−broach
2075−broad
2076−broadcast
2077−broadcloth
2078−broadsheet
2079−broadside
2080−broadways
2081−broadwise
2082−brocade
2083−broccoli
2084−brochure
2085−brogue
2086−broil
2087−broke
2088−broken
2089−broker
2090−brolly
2091−bromide
2092−bromine
2093−bronchi
2094−bronco
2095−bronze
2096−brooch
2097−brood
2098−brook
2099−broom
2100−bros
2101−broth
2102−brothel
2103−brother
2104−brougham
2105−brouhaha
2106−brow
2107−browbeat
2108−brown
2109−brownie
2110−browse
2111−bruin
2112−bruise
2113−bruit
2114−brunch
2115−brunette
2116−brunt
2117−brush
2118−brusque
2119−brussels
2120−brutal
2121−brute
2122−bubble
2123−bubonic
2124−buccaneer
2125−buck
2126−bucket
2127−buckle
2128−buckler
2129−buckram
2130−buckshot
2131−buckwheat
2132−bucolic
2133−bud
2134−buddhism
2135−buddy
2136−budge
2137−budgerigar
2138−budget
2139−budgie
2140−buff
2141−buffalo
2142−buffer
2143−buffet
2144−buffoon
2145−bug
2146−bugaboo
2147−bugbear
2148−bugger
2149−buggy
2150−bugle
2151−buhl
2152−build
2153−building
2154−bulb
2155−bulbul
2156−bulge
2157−bulk
2158−bulkhead
2159−bull
2160−bullet
2161−bulletin
2162−bullion
2163−bullock
2164−bully
2165−bulrush
2166−bulwark
2167−bum
2168−bumboat
2169−bump
2170−bumper
2171−bumpkin
2172−bumptious
2173−bun
2174−buna
2175−bunch
2176−bundle
2177−bung
2178−bungalow
2179−bungle
2180−bunion
2181−bunk
2182−bunker
2183−bunkum
2184−bunny
2185−bunsen
2186−bunting
2187−buoy
2188−buoyancy
2189−buoyant
2190−bur
2191−burberry
2192−burble
2193−burden
2194−burdock
2195−bureau
2196−bureaucracy
2197−bureaucrat
2198−burette
2199−burg
2200−burgeon
2201−burgess
2202−burgh
2203−burgher
2204−burglar
2205−burgomaster
2206−burgundy
2207−burial
2208−burke
2209−burlap
2210−burlesque
2211−burly
2212−burn
2213−burner
2214−burning
2215−burnish
2216−burnouse
2217−burp
2218−burr
2219−burrow
2220−bursar
2221−burst
2222−burthen
2223−burton
2224−bury
2225−bus
2226−busby
2227−bush
2228−bushel
2229−busier
2230−busiest
2231−business
2232−busker
2233−bust
2234−bustard
2235−buster
2236−bustle
2237−busy
2238−but
2239−butane
2240−butch
2241−butcher
2242−butler
2243−butt
2244−butter
2245−butterfly
2246−buttery
2247−buttock
2248−button
2249−buttress
2250−buxom
2251−buy
2252−buzz
2253−buzzard
2254−by
2255−bye
2256−bygone
2257−bypath
2258−byplay
2259−bystander
2260−byword
2261−c
2262−cab
2263−cabal
2264−cabaret
2265−cabbage
2266−cabby
2267−caber
2268−cabin
2269−cabinet
2270−cable
2271−caboodle
2272−caboose
2273−cacao
2274−cache
2275−cachet
2276−cachou
2277−cackle
2278−cacophony
2279−cactus
2280−cad
2281−cadaver
2282−caddie
2283−caddy
2284−cadence
2285−cadenza
2286−cadet
2287−cadge
2288−cadmium
2289−cadre
2290−caesar
2291−caesura
2292−cafe
2293−cafeteria
2294−caff
2295−caffeine
2296−caftan
2297−cage
2298−cagey
2299−cagoule
2300−cahoots
2301−caiman
2302−cairn
2303−caisson
2304−caitiff
2305−cajole
2306−cake
2307−calabash
2308−calamity
2309−calcify
2310−calcine
2311−calcium
2312−calculable
2313−calculate
2314−calculus
2315−caldron
2316−calendar
2317−calender
2318−calends
2319−calf
2320−calibrate
2321−calico
2322−calif
2323−calipers
2324−caliph
2325−calisthenics
2326−calk
2327−call
2328−calligraphy
2329−calliope
2330−callipers
2331−callisthenics
2332−callosity
2333−callous
2334−callow
2335−callus
2336−calm
2337−calomel
2338−calorie
2339−calumny
2340−calvary
2341−calve
2342−calvinism
2343−calypso
2344−calyx
2345−cam
2346−camaraderie
2347−camber
2348−cambric
2349−camel
2350−camellia
2351−camembert
2352−cameo
2353−camera
2354−camion
2355−camomile
2356−camouflage
2357−camp
2358−campaign
2359−campanile
2360−campanula
2361−camphor
2362−campion
2363−campus
2364−can
2365−canadian
2366−canal
2367−canape
2368−canard
2369−canary
2370−canasta
2371−cancan
2372−cancel
2373−cancer
2374−candelabrum
2375−candid
2376−candidate
2377−candied
2378−candle
2379−candour
2380−candy
2381−candytuft
2382−cane
2383−canine
2384−canister
2385−canker
2386−canna
2387−cannabis
2388−canned
2389−cannery
2390−cannibal
2391−cannon
2392−cannot
2393−canny
2394−canoe
2395−canon
2396−canonize
2397−canopy
2398−cant
2399−cantab
2400−cantaloup
2401−cantankerous
2402−cantata
2403−canteen
2404−canter
2405−canticle
2406−cantilever
2407−canto
2408−canton
2409−cantonment
2410−cantor
2411−canuck
2412−canvas
2413−canvass
2414−canyon
2415−cap
2416−capability
2417−capable
2418−capacious
2419−capacity
2420−caparison
2421−cape
2422−caper
2423−capillary
2424−capital
2425−capitalism
2426−capitalize
2427−capitation
2428−capitol
2429−capitulate
2430−capon
2431−caprice
2432−capricious
2433−capricorn
2434−capsicum
2435−capsize
2436−capstan
2437−capsule
2438−captain
2439−caption
2440−captious
2441−captivate
2442−captive
2443−captor
2444−capture
2445−car
2446−carafe
2447−caramel
2448−carapace
2449−carat
2450−caravan
2451−caraway
2452−carbide
2453−carbine
2454−carbohydrate
2455−carbon
2456−carborundum
2457−carboy
2458−carbuncle
2459−carburettor
2460−carcase
2461−carcass
2462−card
2463−cardamom
2464−cardboard
2465−cardiac
2466−cardigan
2467−cardinal
2468−care
2469−careen
2470−career
2471−careful
2472−careless
2473−caress
2474−caret
2475−cargo
2476−caribou
2477−caricature
2478−caries
2479−carillon
2480−carmelite
2481−carmine
2482−carnage
2483−carnal
2484−carnation
2485−carnival
2486−carnivore
2487−carol
2488−carouse
2489−carp
2490−carpal
2491−carpenter
2492−carpet
2493−carriage
2494−carrier
2495−carrion
2496−carrot
2497−carry
2498−cart
2499−cartel
2500−cartilage
2501−cartographer
2502−carton
2503−cartoon
2504−cartridge
2505−carve
2506−caryatid
2507−cascade
2508−case
2509−casein
2510−casement
2511−cash
2512−cashew
2513−cashier
2514−cashmere
2515−casing
2516−casino
2517−cask
2518−casket
2519−cassava
2520−casserole
2521−cassette
2522−cassock
2523−cassowary
2524−cast
2525−castanets
2526−castaway
2527−caste
2528−castellated
2529−caster
2530−castigate
2531−castle
2532−castor
2533−castrate
2534−casual
2535−casualty
2536−casuist
2537−cat
2538−cataclysm
2539−catacombs
2540−catafalque
2541−catalepsy
2542−catalogue
2543−catalpa
2544−catalysis
2545−catamaran
2546−catapult
2547−cataract
2548−catarrh
2549−catastrophe
2550−catch
2551−catchment
2552−catchup
2553−catechism
2554−catechize
2555−categorical
2556−category
2557−cater
2558−caterpillar
2559−caterwaul
2560−catgut
2561−catharsis
2562−cathedral
2563−cathode
2564−catholic
2565−catkin
2566−catsup
2567−cattish
2568−cattle
2569−catty
2570−caucasian
2571−caucus
2572−caught
2573−caul
2574−cauldron
2575−cauliflower
2576−caulk
2577−causal
2578−cause
2579−causerie
2580−causeway
2581−caustic
2582−cauterize
2583−caution
2584−cautious
2585−cavalcade
2586−cavalier
2587−cavalry
2588−cave
2589−caveat
2590−cavern
2591−caviar
2592−caviare
2593−cavil
2594−cavity
2595−cavort
2596−caw
2597−cayenne
2598−cayman
2599−caymen
2600−cease
2601−cedar
2602−cede
2603−cedilla
2604−ceiling
2605−celandine
2606−celebrant
2607−celebrate
2608−celerity
2609−celery
2610−celestial
2611−celibacy
2612−cell
2613−cellar
2614−cello
2615−cellophane
2616−cellular
2617−celluloid
2618−cellulose
2619−celsius
2620−celt
2621−cement
2622−cemetery
2623−cenotaph
2624−censer
2625−censor
2626−censorious
2627−censure
2628−census
2629−cent
2630−centaur
2631−centenarian
2632−centenary
2633−centennial
2634−center
2635−centigrade
2636−centime
2637−centipede
2638−central
2639−centralize
2640−centre
2641−centrifugal
2642−centripetal
2643−centurion
2644−century
2645−ceramic
2646−cereal
2647−cerebral
2648−cerebration
2649−ceremonial
2650−ceremonious
2651−ceremony
2652−cerise
2653−cert
2654−certain
2655−certifiable
2656−certificate
2657−certify
2658−certitude
2659−cerulean
2660−cervix
2661−cessation
2662−cession
2663−cesspit
2664−chafe
2665−chaff
2666−chaffinch
2667−chagrin
2668−chain
2669−chair
2670−chaise
2671−chalet
2672−chalice
2673−chalk
2674−challenge
2675−chamber
2676−chamberlain
2677−chameleon
2678−chamois
2679−chamomile
2680−champ
2681−champagne
2682−champion
2683−chance
2684−chancel
2685−chancellery
2686−chancellor
2687−chancery
2688−chancy
2689−chandelier
2690−chandler
2691−change
2692−changeling
2693−channel
2694−chant
2695−chantey
2696−chanty
2697−chaos
2698−chap
2699−chapel
2700−chaperon
2701−chapfallen
2702−chaplain
2703−chaplet
2704−chapman
2705−chapter
2706−char
2707−character
2708−charade
2709−charcoal
2710−chard
2711−charge
2712−chargeable
2713−charger
2714−chariot
2715−charisma
2716−charitable
2717−charity
2718−charivari
2719−charlady
2720−charlatan
2721−charleston
2722−charlock
2723−charm
2724−chart
2725−charter
2726−chartism
2727−chartreuse
2728−charwoman
2729−chary
2730−charybdis
2731−chase
2732−chasm
2733−chassis
2734−chaste
2735−chasten
2736−chastise
2737−chastity
2738−chasuble
2739−chat
2740−chateau
2741−chatelaine
2742−chattel
2743−chatter
2744−chauffeur
2745−chauvinism
2746−chaw
2747−cheap
2748−cheapen
2749−cheat
2750−check
2751−checker
2752−checkers
2753−checkmate
2754−cheddar
2755−cheek
2756−cheep
2757−cheer
2758−cheerful
2759−cheerio
2760−cheerless
2761−cheery
2762−cheese
2763−cheetah
2764−chef
2765−chemical
2766−chemise
2767−chemist
2768−chemistry
2769−chemotherapy
2770−chenille
2771−cheque
2772−chequer
2773−cherish
2774−cheroot
2775−cherry
2776−cherub
2777−chervil
2778−chess
2779−chest
2780−chesterfield
2781−chestnut
2782−chevron
2783−chew
2784−chianti
2785−chiaroscuro
2786−chic
2787−chicanery
2788−chichi
2789−chick
2790−chicken
2791−chicle
2792−chicory
2793−chide
2794−chief
2795−chieftain
2796−chiffon
2797−chiffonier
2798−chignon
2799−chilblain
2800−child
2801−chile
2802−chili
2803−chill
2804−chilli
2805−chilly
2806−chimaera
2807−chime
2808−chimera
2809−chimney
2810−chimp
2811−chimpanzee
2812−chin
2813−china
2814−chinchilla
2815−chine
2816−chink
2817−chintz
2818−chip
2819−chipmunk
2820−chippendale
2821−chiropodist
2822−chiropractor
2823−chirp
2824−chirpy
2825−chirrup
2826−chisel
2827−chit
2828−chivalry
2829−chive
2830−chivvy
2831−chivy
2832−chloride
2833−chlorine
2834−chloroform
2835−chlorophyll
2836−chock
2837−chocolate
2838−choice
2839−choir
2840−choke
2841−choker
2842−chokey
2843−choky
2844−choler
2845−cholera
2846−choose
2847−choosey
2848−choosy
2849−chop
2850−chopper
2851−choppy
2852−chopsticks
2853−choral
2854−chorale
2855−chord
2856−chore
2857−choreography
2858−chorister
2859−chortle
2860−chorus
2861−chose
2862−chosen
2863−chow
2864−chowder
2865−christ
2866−christen
2867−christendom
2868−christian
2869−christmas
2870−chromatic
2871−chrome
2872−chromium
2873−chromosome
2874−chronic
2875−chronicle
2876−chronological
2877−chronology
2878−chronometer
2879−chrysalis
2880−chrysanthemum
2881−chubby
2882−chuck
2883−chuckle
2884−chug
2885−chukker
2886−chum
2887−chump
2888−chunk
2889−church
2890−churl
2891−churn
2892−chute
2893−chutney
2894−cicada
2895−cicala
2896−cicatrice
2897−cicerone
2898−cider
2899−cigar
2900−cigarette
2901−cinch
2902−cinchona
2903−cincture
2904−cinder
2905−cinderella
2906−cinema
2907−cinnamon
2908−cinquefoil
2909−cipher
2910−circa
2911−circle
2912−circlet
2913−circuit
2914−circuitous
2915−circular
2916−circulate
2917−circulation
2918−circumcise
2919−circumference
2920−circumflex
2921−circumlocution
2922−circumnavigate
2923−circumscribe
2924−circumspect
2925−circumstance
2926−circumstantial
2927−circumvent
2928−circus
2929−cirrhosis
2930−cirrus
2931−cissy
2932−cistern
2933−citadel
2934−cite
2935−citizen
2936−citric
2937−citron
2938−citrous
2939−citrus
2940−city
2941−civet
2942−civic
2943−civies
2944−civil
2945−civilian
2946−civilization
2947−civilize
2948−civvies
2949−clack
2950−clad
2951−claim
2952−clairvoyance
2953−clam
2954−clamber
2955−clammy
2956−clamour
2957−clamp
2958−clan
2959−clandestine
2960−clang
2961−clangour
2962−clank
2963−clannish
2964−clansman
2965−clap
2966−clapboard
2967−clapper
2968−claptrap
2969−claque
2970−claret
2971−clarify
2972−clarinet
2973−clarion
2974−clarity
2975−clash
2976−clasp
2977−class
2978−classic
2979−classical
2980−classicist
2981−classification
2982−classify
2983−classy
2984−clatter
2985−clause
2986−claustrophobia
2987−clavichord
2988−clavicle
2989−claw
2990−clay
2991−clean
2992−cleanly
2993−cleanse
2994−clear
2995−clearance
2996−clearing
2997−clearly
2998−cleat
2999−cleavage
3000−cleave
3001−cleaver
3002−clef
3003−cleft
3004−clematis
3005−clemency
3006−clement
3007−clench
3008−clerestory
3009−clergy
3010−cleric
3011−clerical
3012−clerihew
3013−clerk
3014−clever
3015−clew
3016−cliche
3017−click
3018−client
3019−cliff
3020−climacteric
3021−climactic
3022−climate
3023−climax
3024−climb
3025−clime
3026−clinch
3027−cling
3028−clinic
3029−clinical
3030−clink
3031−clinker
3032−clip
3033−clipper
3034−clique
3035−clitoris
3036−cloak
3037−clobber
3038−cloche
3039−clock
3040−clod
3041−clog
3042−cloisonne
3043−cloister
3044−clone
3045−close
3046−closet
3047−closure
3048−clot
3049−cloth
3050−clothe
3051−clothes
3052−clothier
3053−clothing
3054−cloture
3055−cloud
3056−clout
3057−clove
3058−cloven
3059−clover
3060−clown
3061−cloy
3062−club
3063−cluck
3064−clue
3065−clump
3066−clumsy
3067−clung
3068−clunk
3069−cluster
3070−clutch
3071−clutter
3072−coach
3073−coagulate
3074−coal
3075−coalesce
3076−coalition
3077−coaming
3078−coarse
3079−coast
3080−coat
3081−coatee
3082−coax
3083−cob
3084−cobalt
3085−cobber
3086−cobble
3087−cobbler
3088−cobra
3089−cobweb
3090−cocaine
3091−cochineal
3092−cochlea
3093−cock
3094−cockade
3095−cockatoo
3096−cockchafer
3097−cocker
3098−cockerel
3099−cockhorse
3100−cockle
3101−cockney
3102−cockpit
3103−cockroach
3104−cockscomb
3105−cocksure
3106−cocktail
3107−cocky
3108−coco
3109−cocoa
3110−cocoon
3111−cocotte
3112−cod
3113−coda
3114−coddle
3115−code
3116−codeine
3117−codex
3118−codger
3119−codices
3120−codicil
3121−codify
3122−codling
3123−codpiece
3124−coerce
3125−coeval
3126−coexist
3127−coffee
3128−coffer
3129−coffin
3130−cog
3131−cogent
3132−cogitate
3133−cognac
3134−cognate
3135−cognition
3136−cognizance
3137−cognomen
3138−cohabit
3139−cohere
3140−cohesion
3141−cohort
3142−coif
3143−coiffeur
3144−coiffure
3145−coign
3146−coil
3147−coin
3148−coincide
3149−coincidence
3150−coir
3151−coition
3152−coitus
3153−coke
3154−cokernut
3155−col
3156−cola
3157−colander
3158−cold
3159−coleslaw
3160−colic
3161−colitis
3162−collaborate
3163−collage
3164−collapse
3165−collar
3166−collate
3167−collateral
3168−collation
3169−colleague
3170−collect
3171−collection
3172−collective
3173−collector
3174−colleen
3175−college
3176−collide
3177−collie
3178−collier
3179−colliery
3180−collision
3181−collocate
3182−colloquial
3183−colloquy
3184−collusion
3185−collywobbles
3186−colon
3187−colonel
3188−colonial
3189−colonist
3190−colonize
3191−colonnade
3192−colony
3193−color
3194−coloratura
3195−colossal
3196−colossus
3197−colour
3198−colt
3199−colter
3200−columbine
3201−column
3202−coma
3203−comb
3204−combat
3205−combination
3206−combine
3207−combustible
3208−combustion
3209−come
3210−comedian
3211−comedy
3212−comely
3213−comer
3214−comestible
3215−comet
3216−comfit
3217−comfort
3218−comfortable
3219−comfrey
3220−comfy
3221−comic
3222−comical
3223−coming
3224−comity
3225−comma
3226−command
3227−commandant
3228−commandeer
3229−commander
3230−commandment
3231−commando
3232−commemorate
3233−commemoration
3234−commence
3235−commend
3236−commensurable
3237−commensurate
3238−comment
3239−commentary
3240−commerce
3241−commercial
3242−commination
3243−commingle
3244−commiserate
3245−commissar
3246−commissariat
3247−commissary
3248−commission
3249−commissionaire
3250−commissioner
3251−commit
3252−committee
3253−commode
3254−commodious
3255−commodity
3256−commodore
3257−common
3258−commonalty
3259−commoner
3260−commonplace
3261−commons
3262−commonwealth
3263−commotion
3264−communal
3265−commune
3266−communicable
3267−communicant
3268−communicate
3269−communication
3270−communicative
3271−communion
3272−communique
3273−communism
3274−community
3275−commutable
3276−commutation
3277−commutator
3278−commute
3279−compact
3280−companion
3281−company
3282−comparable
3283−comparative
3284−compare
3285−comparison
3286−compartment
3287−compass
3288−compassion
3289−compatible
3290−compatriot
3291−compeer
3292−compel
3293−compendious
3294−compendium
3295−compensate
3296−compensation
3297−compere
3298−compete
3299−competence
3300−competent
3301−competition
3302−competitive
3303−competitor
3304−compile
3305−complacence
3306−complacent
3307−complain
3308−complainant
3309−complaint
3310−complaisance
3311−complement
3312−complete
3313−completion
3314−complex
3315−complexion
3316−compliance
3317−compliant
3318−complicate
3319−complication
3320−complicity
3321−compliment
3322−complimentary
3323−complin
3324−compline
3325−comply
3326−component
3327−comport
3328−compose
3329−composer
3330−composite
3331−composition
3332−compositor
3333−compost
3334−composure
3335−compote
3336−compound
3337−comprehend
3338−comprehensible
3339−comprehension
3340−comprehensive
3341−compress
3342−compression
3343−comprise
3344−compromise
3345−comptroller
3346−compulsion
3347−compulsive
3348−compulsory
3349−compunction
3350−computation
3351−compute
3352−computer
3353−comrade
3354−con
3355−concatenation
3356−concave
3357−conceal
3358−concede
3359−conceit
3360−conceive
3361−concentrate
3362−concentration
3363−concentric
3364−concept
3365−conception
3366−concern
3367−concert
3368−concertina
3369−concerto
3370−concession
3371−conch
3372−concierge
3373−conciliate
3374−conciliation
3375−concise
3376−conclave
3377−conclude
3378−conclusion
3379−conclusive
3380−concoct
3381−concomitant
3382−concord
3383−concordance
3384−concordant
3385−concordat
3386−concourse
3387−concrete
3388−concubine
3389−concupiscence
3390−concur
3391−concurrent
3392−concuss
3393−concussion
3394−condemn
3395−condensation
3396−condense
3397−condenser
3398−condescend
3399−condign
3400−condiment
3401−condition
3402−conditional
3403−condole
3404−condominium
3405−condone
3406−condor
3407−conduce
3408−conduct
3409−conductor
3410−conduit
3411−cone
3412−coney
3413−confab
3414−confabulate
3415−confection
3416−confederacy
3417−confederate
3418−confer
3419−conference
3420−confess
3421−confession
3422−confessional
3423−confessor
3424−confetti
3425−confidant
3426−confide
3427−confidence
3428−confident
3429−confidential
3430−configuration
3431−confine
3432−confines
3433−confirm
3434−confirmation
3435−confiscate
3436−conflagration
3437−conflict
3438−confluence
3439−conform
3440−conformation
3441−conformist
3442−conformity
3443−confound
3444−confrere
3445−confront
3446−confrontation
3447−confucian
3448−confuse
3449−confusion
3450−confute
3451−conge
3452−congeal
3453−congenial
3454−congenital
3455−conger
3456−congested
3457−congestion
3458−conglomerate
3459−conglomeration
3460−congratulate
3461−congratulation
3462−congregate
3463−congregation
3464−congress
3465−congruent
3466−congruous
3467−conic
3468−conifer
3469−conjecture
3470−conjoin
3471−conjugal
3472−conjugate
3473−conjunction
3474−conjunctive
3475−conjuncture
3476−conjuration
3477−conjure
3478−conk
3479−conker
3480−connect
3481−connection
3482−connective
3483−connexion
3484−connive
3485−connoisseur
3486−connote
3487−connubial
3488−conquer
3489−conquest
3490−conquistador
3491−consanguinity
3492−conscience
3493−conscientious
3494−conscious
3495−consciousness
3496−conscript
3497−consecrate
3498−consecration
3499−consecutive
3500−consensus
3501−consent
3502−consequence
3503−consequent
3504−consequential
3505−conservancy
3506−conservation
3507−conservatism
3508−conservative
3509−conservatoire
3510−conservatory
3511−conserve
3512−consider
3513−considerable
3514−considerate
3515−consideration
3516−considering
3517−consign
3518−consist
3519−consistence
3520−consistency
3521−consistent
3522−consistory
3523−consolation
3524−consolatory
3525−console
3526−consolidate
3527−consolidation
3528−consols
3529−consomme
3530−consonance
3531−consonant
3532−consort
3533−consortium
3534−conspectus
3535−conspicuous
3536−conspiracy
3537−conspire
3538−constable
3539−constancy
3540−constant
3541−constellation
3542−consternation
3543−constipate
3544−constipated
3545−constipation
3546−constituency
3547−constituent
3548−constitute
3549−constitution
3550−constitutional
3551−constitutive
3552−constrain
3553−constraint
3554−constrict
3555−construct
3556−construction
3557−constructive
3558−construe
3559−consubstantiation
3560−consul
3561−consular
3562−consulate
3563−consult
3564−consultant
3565−consultation
3566−consultative
3567−consume
3568−consumer
3569−consummate
3570−consummation
3571−consumption
3572−consumptive
3573−contact
3574−contagion
3575−contagious
3576−contain
3577−contaminate
3578−contamination
3579−contemn
3580−contemplate
3581−contemplation
3582−contemplative
3583−contemporaneous
3584−contemporary
3585−contempt
3586−contemptible
3587−contemptuous
3588−contend
3589−content
3590−contention
3591−contentious
3592−conterminous
3593−contest
3594−context
3595−contiguity
3596−contiguous
3597−continence
3598−continent
3599−contingency
3600−contingent
3601−continual
3602−continuance
3603−continuation
3604−continue
3605−continuity
3606−continuous
3607−contort
3608−contortion
3609−contour
3610−contraband
3611−contrabass
3612−contraception
3613−contract
3614−contraction
3615−contradict
3616−contradistinction
3617−contradistinguish
3618−contralto
3619−contraption
3620−contrapuntal
3621−contrariety
3622−contrariwise
3623−contrary
3624−contrast
3625−contravene
3626−contravention
3627−contretemps
3628−contribute
3629−contribution
3630−contributory
3631−contrite
3632−contrition
3633−contrivance
3634−contrive
3635−control
3636−controller
3637−controversial
3638−controversy
3639−controvert
3640−contumacious
3641−contumacy
3642−contumelious
3643−contumely
3644−contuse
3645−conundrum
3646−conurbation
3647−convalesce
3648−convection
3649−convector
3650−convene
3651−convenience
3652−convenient
3653−convent
3654−conventicle
3655−convention
3656−conventional
3657−conventionality
3658−converge
3659−conversant
3660−conversation
3661−converse
3662−conversion
3663−convert
3664−convertible
3665−convex
3666−convey
3667−conveyance
3668−convict
3669−conviction
3670−convince
3671−convivial
3672−convocation
3673−convoke
3674−convoluted
3675−convolution
3676−convolvulus
3677−convoy
3678−convulse
3679−convulsion
3680−convulsive
3681−cony
3682−coo
3683−cook
3684−cooker
3685−cookery
3686−cookie
3687−cooky
3688−cool
3689−coolant
3690−cooler
3691−coolie
3692−coon
3693−coop
3694−cooper
3695−coot
3696−cop
3697−cope
3698−copeck
3699−copernican
3700−coping
3701−copious
3702−copper
3703−coppice
3704−copra
3705−copse
3706−copt
3707−copula
3708−copulate
3709−copy
3710−copyhold
3711−copyright
3712−coquetry
3713−coquette
3714−coracle
3715−coral
3716−corbel
3717−cord
3718−cordage
3719−cordial
3720−cordite
3721−cordon
3722−cords
3723−corduroy
3724−core
3725−corgi
3726−corinthian
3727−cork
3728−corkage
3729−corker
3730−corm
3731−cormorant
3732−corn
3733−cornea
3734−cornelian
3735−corner
3736−cornet
3737−cornice
3738−cornucopia
3739−corny
3740−corolla
3741−corollary
3742−corona
3743−coronary
3744−coronation
3745−coroner
3746−coronet
3747−corporal
3748−corporate
3749−corporation
3750−corporeal
3751−corps
3752−corpse
3753−corpulent
3754−corpus
3755−corpuscle
3756−corral
3757−correct
3758−correction
3759−correctitude
3760−corrective
3761−correlate
3762−correlation
3763−correlative
3764−correspond
3765−correspondence
3766−correspondent
3767−corridor
3768−corrie
3769−corrigendum
3770−corrigible
3771−corroborate
3772−corroboration
3773−corrode
3774−corrosive
3775−corrugate
3776−corrupt
3777−corruption
3778−corsage
3779−corsair
3780−corse
3781−corselet
3782−corset
3783−corslet
3784−cortege
3785−cortex
3786−cortisone
3787−corundum
3788−coruscate
3789−corvee
3790−corvette
3791−cos
3792−cosh
3793−cosher
3794−cosine
3795−cosmetic
3796−cosmic
3797−cosmogony
3798−cosmonaut
3799−cosmopolitan
3800−cosmos
3801−cosset
3802−cost
3803−costermonger
3804−costive
3805−costly
3806−costume
3807−cosy
3808−cot
3809−cote
3810−coterie
3811−coterminous
3812−cotilion
3813−cotillion
3814−cottage
3815−cottar
3816−cotter
3817−cotton
3818−cotyledon
3819−couch
3820−couchant
3821−couchette
3822−cougar
3823−cough
3824−could
3825−couldst
3826−coulter
3827−council
3828−councillor
3829−counsel
3830−counsellor
3831−count
3832−countenance
3833−counter
3834−counteract
3835−counterbalance
3836−counterblast
3837−counterclaim
3838−counterfeit
3839−counterfoil
3840−countermand
3841−countermine
3842−counteroffer
3843−counterpane
3844−counterpart
3845−counterplot
3846−counterpoint
3847−counterpoise
3848−countersign
3849−countersink
3850−countertenor
3851−countervail
3852−countess
3853−countless
3854−countrified
3855−country
3856−countryman
3857−countryside
3858−county
3859−coup
3860−coupe
3861−couple
3862−couplet
3863−coupling
3864−coupon
3865−courage
3866−courageous
3867−courgette
3868−courier
3869−course
3870−courser
3871−court
3872−courteous
3873−courtesan
3874−courtesy
3875−courtier
3876−courtly
3877−courtship
3878−courtyard
3879−cousin
3880−cove
3881−coven
3882−covenant
3883−coventry
3884−cover
3885−coverage
3886−coverlet
3887−covert
3888−covet
3889−covetous
3890−covey
3891−cow
3892−coward
3893−cowardice
3894−cower
3895−cowl
3896−cowpox
3897−cowrie
3898−cowslip
3899−cox
3900−coxcomb
3901−coxswain
3902−coy
3903−coyote
3904−coypu
3905−cozen
3906−cozy
3907−crab
3908−crabbed
3909−crack
3910−cracker
3911−crackers
3912−crackle
3913−crackling
3914−crackpot
3915−cracksman
3916−cradle
3917−craft
3918−craftsman
3919−crag
3920−crake
3921−cram
3922−cramp
3923−crampon
3924−cranberry
3925−crane
3926−cranial
3927−cranium
3928−crank
3929−cranny
3930−crap
3931−crape
3932−craps
3933−crash
3934−crass
3935−crate
3936−crater
3937−cravat
3938−crave
3939−craven
3940−crawfish
3941−crawl
3942−crayfish
3943−crayon
3944−craze
3945−crazed
3946−crazy
3947−creak
3948−cream
3949−crease
3950−create
3951−creation
3952−creative
3953−creator
3954−creature
3955−creche
3956−credence
3957−credentials
3958−credible
3959−credit
3960−creditable
3961−creditor
3962−credo
3963−credulity
3964−credulous
3965−creed
3966−creek
3967−creel
3968−creep
3969−creeper
3970−creepy
3971−cremate
3972−crenellated
3973−creole
3974−creosote
3975−crepe
3976−crepitate
3977−crept
3978−crepuscular
3979−crescendo
3980−crescent
3981−cress
3982−crest
3983−cretacious
3984−cretin
3985−cretonne
3986−crevasse
3987−crevice
3988−crew
3989−crib
3990−cribbage
3991−crick
3992−cricket
3993−cried
3994−crier
3995−cries
3996−crikey
3997−crime
3998−criminal
3999−criminology
4000−crimp
4001−crimson
4002−cringe
4003−crinkle
4004−crinoline
4005−cripes
4006−cripple
4007−crisis
4008−crisp
4009−crisscross
4010−criterion
4011−critic
4012−critical
4013−criticism
4014−criticize
4015−critique
4016−croak
4017−crochet
4018−crock
4019−crockery
4020−crocodile
4021−crocus
4022−croesus
4023−croft
4024−cromlech
4025−crone
4026−crony
4027−crook
4028−crooked
4029−croon
4030−crop
4031−cropper
4032−croquet
4033−croquette
4034−crore
4035−crosier
4036−cross
4037−crossbar
4038−crossbeam
4039−crossbenches
4040−crossbones
4041−crossbow
4042−crossbred
4043−crossbreed
4044−crosscountry
4045−crosscut
4046−crosse
4047−crosseyed
4048−crossfire
4049−crossing
4050−crosskeys
4051−crosspatch
4052−crossroad
4053−crosstrees
4054−crosswalk
4055−crosswind
4056−crossword
4057−crotch
4058−crotchet
4059−crouch
4060−croup
4061−croupier
4062−crow
4063−crowbar
4064−crowd
4065−crown
4066−crozier
4067−crucial
4068−crucible
4069−crucifix
4070−crucifixion
4071−cruciform
4072−crucify
4073−crude
4074−crudity
4075−cruel
4076−cruelty
4077−cruet
4078−cruise
4079−crumb
4080−crumble
4081−crumbly
4082−crumpet
4083−crumple
4084−crunch
4085−crupper
4086−crusade
4087−cruse
4088−crush
4089−crust
4090−crustacean
4091−crusted
4092−crusty
4093−crutch
4094−crux
4095−cry
4096−crying
4097−crypt
4098−cryptic
4099−cryptogram
4100−crystal
4101−crystalline
4102−crystallize
4103−cub
4104−cube
4105−cubic
4106−cubical
4107−cubicle
4108−cubism
4109−cubit
4110−cuckold
4111−cuckoo
4112−cucumber
4113−cud
4114−cuddle
4115−cudgel
4116−cue
4117−cuff
4118−cuirass
4119−cuisine
4120−culinary
4121−cull
4122−cullender
4123−culminate
4124−culpable
4125−culprit
4126−cult
4127−cultivable
4128−cultivate
4129−cultivation
4130−cultivator
4131−cultural
4132−culture
4133−culvert
4134−cumber
4135−cumbersome
4136−cumbrous
4137−cummerbund
4138−cumulative
4139−cumulus
4140−cuneiform
4141−cunning
4142−cunt
4143−cup
4144−cupboard
4145−cupid
4146−cupidity
4147−cupola
4148−cuppa
4149−cupping
4150−cupric
4151−cur
4152−curable
4153−curacao
4154−curacy
4155−curate
4156−curative
4157−curator
4158−curb
4159−curd
4160−curdle
4161−cure
4162−curfew
4163−curio
4164−curiosity
4165−curious
4166−curl
4167−curlew
4168−curling
4169−curly
4170−curmudgeon
4171−currant
4172−currency
4173−current
4174−curriculum
4175−currish
4176−curry
4177−curse
4178−cursed
4179−cursive
4180−cursory
4181−curst
4182−curt
4183−curtail
4184−curtain
4185−curtsey
4186−curtsy
4187−curvature
4188−curve
4189−cushion
4190−cushy
4191−cusp
4192−cuspidor
4193−cuss
4194−cussed
4195−custard
4196−custodian
4197−custody
4198−custom
4199−customary
4200−customer
4201−cut
4202−cute
4203−cuticle
4204−cutlass
4205−cutler
4206−cutlet
4207−cutpurse
4208−cutter
4209−cutting
4210−cuttlefish
4211−cutworm
4212−cyanide
4213−cybernetics
4214−cyclamen
4215−cycle
4216−cyclic
4217−cyclical
4218−cyclist
4219−cyclone
4220−cyclopaedia
4221−cyclopean
4222−cyclostyle
4223−cyclotron
4224−cyder
4225−cygnet
4226−cylinder
4227−cymbal
4228−cynic
4229−cynical
4230−cynosure
4231−cypher
4232−cypress
4233−cyrillic
4234−cyst
4235−czar
4236−czech
4237−d
4238−dab
4239−dabble
4240−dace
4241−dacha
4242−dachshund
4243−dacoit
4244−dactyl
4245−dad
4246−daddy
4247−dado
4248−daemon
4249−daffodil
4250−daft
4251−dagger
4252−dago
4253−daguerreotype
4254−dahlia
4255−daily
4256−dainty
4257−dairy
4258−dais
4259−daisy
4260−dale
4261−dalliance
4262−dally
4263−dalmation
4264−dam
4265−damage
4266−damascene
4267−damask
4268−dame
4269−damn
4270−damnable
4271−damnation
4272−damned
4273−damocles
4274−damp
4275−dampen
4276−damper
4277−damsel
4278−damson
4279−dance
4280−dandelion
4281−dander
4282−dandle
4283−dandruff
4284−dandy
4285−dane
4286−danger
4287−dangerous
4288−dangle
4289−daniel
4290−danish
4291−dank
4292−daphne
4293−dapper
4294−dapple
4295−dare
4296−daring
4297−dark
4298−darken
4299−darkey
4300−darkie
4301−darky
4302−darling
4303−darn
4304−dart
4305−dash
4306−dastard
4307−data
4308−date
4309−dative
4310−datum
4311−daub
4312−daughter
4313−daunt
4314−dauntless
4315−dauphin
4316−davenport
4317−davit
4318−daw
4319−dawdle
4320−dawn
4321−day
4322−daylight
4323−daze
4324−dazzle
4325−deacon
4326−dead
4327−deaden
4328−deadlock
4329−deadly
4330−deaf
4331−deafen
4332−deal
4333−dealer
4334−dealing
4335−dealt
4336−dean
4337−dear
4338−dearie
4339−dearth
4340−deary
4341−death
4342−deathless
4343−deathlike
4344−deathly
4345−deb
4346−debacle
4347−debag
4348−debar
4349−debark
4350−debase
4351−debatable
4352−debate
4353−debauch
4354−debenture
4355−debilitate
4356−debility
4357−debit
4358−debonair
4359−debouch
4360−debrief
4361−debris
4362−debt
4363−debug
4364−debunk
4365−debut
4366−debutante
4367−decade
4368−decadence
4369−decadent
4370−decalogue
4371−decamp
4372−decant
4373−decapitate
4374−decarbonize
4375−decasyllable
4376−decay
4377−decease
4378−deceit
4379−deceitful
4380−deceive
4381−decelerate
4382−december
4383−decency
4384−decent
4385−decentralize
4386−deception
4387−deceptive
4388−decibel
4389−decide
4390−deciduous
4391−decimal
4392−decimate
4393−decipher
4394−decision
4395−decisive
4396−deck
4397−declaim
4398−declamation
4399−declaration
4400−declare
4401−declassify
4402−declension
4403−declination
4404−decline
4405−declivity
4406−declutch
4407−decode
4408−decoke
4409−decollete
4410−decolonize
4411−decompose
4412−decompress
4413−decontaminate
4414−decontrol
4415−decor
4416−decorate
4417−decoration
4418−decorative
4419−decorous
4420−decorum
4421−decoy
4422−decrease
4423−decree
4424−decrepit
4425−decry
4426−dedicate
4427−deduce
4428−deduct
4429−deduction
4430−deed
4431−deem
4432−deep
4433−deer
4434−deface
4435−defalcation
4436−defame
4437−default
4438−defeat
4439−defecate
4440−defect
4441−defection
4442−defective
4443−defence
4444−defend
4445−defendant
4446−defense
4447−defensible
4448−defensive
4449−defer
4450−deference
4451−defiance
4452−defiant
4453−deficiency
4454−deficient
4455−deficit
4456−defile
4457−define
4458−definite
4459−definition
4460−definitive
4461−deflate
4462−deflect
4463−deflower
4464−defoliate
4465−deforest
4466−deform
4467−deformity
4468−defraud
4469−defray
4470−defrock
4471−defrost
4472−deft
4473−defunct
4474−defuse
4475−defy
4476−degauss
4477−degenerate
4478−degrade
4479−degree
4480−dehumanize
4481−dehydrate
4482−deify
4483−deign
4484−deism
4485−deity
4486−deject
4487−dekko
4488−delay
4489−delectable
4490−delectation
4491−delegacy
4492−delegate
4493−delegation
4494−delete
4495−deleterious
4496−delft
4497−deliberate
4498−deliberation
4499−delicacy
4500−delicate
4501−delicatessen
4502−delicious
4503−delight
4504−delimit
4505−delineate
4506−delinquency
4507−delinquent
4508−deliquescent
4509−delirious
4510−delirium
4511−deliver
4512−deliverance
4513−delivery
4514−dell
4515−delouse
4516−delphic
4517−delphinium
4518−delta
4519−delude
4520−deluge
4521−delusion
4522−delusive
4523−delve
4524−demagnetize
4525−demagogue
4526−demand
4527−demarcate
4528−demarcation
4529−demarche
4530−demean
4531−demeanour
4532−demented
4533−demerara
4534−demerit
4535−demesne
4536−demigod
4537−demijohn
4538−demilitarize
4539−demimonde
4540−demise
4541−demist
4542−demo
4543−demob
4544−demobilize
4545−democracy
4546−democrat
4547−democratic
4548−democratize
4549−demode
4550−demography
4551−demolish
4552−demon
4553−demonetize
4554−demoniac
4555−demonstrable
4556−demonstrate
4557−demonstration
4558−demonstrative
4559−demonstrator
4560−demoralize
4561−demote
4562−demotic
4563−demur
4564−demure
4565−den
4566−denary
4567−denationalize
4568−denatured
4569−deniable
4570−denial
4571−denier
4572−denigrate
4573−denim
4574−denizen
4575−denominate
4576−denomination
4577−denominator
4578−denote
4579−denouement
4580−denounce
4581−dense
4582−density
4583−dent
4584−dental
4585−dentifrice
4586−dentist
4587−denture
4588−denude
4589−denunciation
4590−deny
4591−deodar
4592−deodorant
4593−deodorize
4594−depart
4595−department
4596−departure
4597−depend
4598−dependant
4599−dependence
4600−dependency
4601−dependent
4602−depict
4603−depilatory
4604−deplane
4605−deplete
4606−deplore
4607−deploy
4608−deponent
4609−depopulate
4610−deport
4611−depose
4612−deposit
4613−deposition
4614−depositor
4615−depository
4616−depot
4617−deprave
4618−depravity
4619−deprecate
4620−depreciate
4621−depredation
4622−depress
4623−depression
4624−depressive
4625−deprive
4626−depth
4627−deputation
4628−depute
4629−deputize
4630−deputy
4631−derail
4632−derange
4633−derate
4634−derby
4635−derelict
4636−derequisition
4637−derestrict
4638−deride
4639−derision
4640−derisive
4641−derisory
4642−derivation
4643−derivative
4644−derive
4645−dermatology
4646−derogate
4647−derogatory
4648−derrick
4649−derv
4650−dervish
4651−desalinate
4652−desalinize
4653−desalt
4654−descale
4655−descant
4656−descend
4657−descent
4658−describe
4659−description
4660−descriptive
4661−descry
4662−desecrate
4663−desegregate
4664−desensitize
4665−desert
4666−deserts
4667−deserve
4668−deserving
4669−deshabille
4670−desiccant
4671−desiccate
4672−desideratum
4673−design
4674−designate
4675−designation
4676−designer
4677−designing
4678−desirable
4679−desire
4680−desirous
4681−desist
4682−desk
4683−desolate
4684−despair
4685−despatch
4686−desperado
4687−desperate
4688−despicable
4689−despise
4690−despite
4691−despoil
4692−despondency
4693−despot
4694−dessert
4695−destination
4696−destine
4697−destiny
4698−destitute
4699−destroy
4700−destructible
4701−destruction
4702−destructive
4703−desuetude
4704−desultory
4705−detach
4706−detachment
4707−detail
4708−detain
4709−detect
4710−detection
4711−detective
4712−detente
4713−detention
4714−deter
4715−detergent
4716−deteriorate
4717−determinant
4718−determinate
4719−determination
4720−determinative
4721−determine
4722−determiner
4723−deterrent
4724−detest
4725−dethrone
4726−detonate
4727−detour
4728−detract
4729−detrain
4730−detribalize
4731−detriment
4732−detritus
4733−deuce
4734−devalue
4735−devastate
4736−develop
4737−development
4738−deviant
4739−deviate
4740−deviation
4741−device
4742−devil
4743−devilish
4744−devilment
4745−devious
4746−devise
4747−devitalize
4748−devoid
4749−devolution
4750−devolve
4751−devote
4752−devotee
4753−devotion
4754−devour
4755−devout
4756−dew
4757−dewlap
4758−dexterity
4759−dexterous
4760−dextrose
4761−dextrous
4762−dhoti
4763−dhow
4764−diabetes
4765−diabetic
4766−diabolic
4767−diacritic
4768−diadem
4769−diaeresis
4770−diagnose
4771−diagnosis
4772−diagnostic
4773−diagonal
4774−diagram
4775−dial
4776−dialect
4777−dialectic
4778−dialogue
4779−diameter
4780−diametrically
4781−diamond
4782−diaper
4783−diaphanous
4784−diaphragm
4785−diarchy
4786−diarrhoea
4787−diary
4788−diaspora
4789−diatonic
4790−diatribe
4791−dibble
4792−dice
4793−dicey
4794−dichotomy
4795−dickens
4796−dicker
4797−dickey
4798−dicky
4799−dictaphone
4800−dictate
4801−dictation
4802−dictator
4803−diction
4804−dictionary
4805−dictum
4806−did
4807−didactic
4808−diddle
4809−die
4810−dieresis
4811−diesel
4812−diet
4813−differ
4814−difference
4815−different
4816−differential
4817−differentiate
4818−difficult
4819−difficulty
4820−diffident
4821−diffract
4822−diffuse
4823−dig
4824−digest
4825−digestion
4826−digestive
4827−digger
4828−digging
4829−digit
4830−dignify
4831−dignitary
4832−dignity
4833−digraph
4834−digress
4835−digs
4836−dike
4837−dilapidated
4838−dilate
4839−dilatory
4840−dilemma
4841−dilettante
4842−diligence
4843−diligent
4844−dill
4845−dilute
4846−dim
4847−dime
4848−dimension
4849−diminish
4850−diminuendo
4851−diminution
4852−diminutive
4853−dimity
4854−dimple
4855−din
4856−dine
4857−diner
4858−dinghy
4859−dingle
4860−dingy
4861−dining
4862−dinky
4863−dinner
4864−dinosaur
4865−dint
4866−diocese
4867−dioxide
4868−dip
4869−diphtheria
4870−diphthong
4871−diploma
4872−diplomacy
4873−diplomat
4874−diplomatic
4875−diplomatist
4876−dipper
4877−dipsomania
4878−diptych
4879−dire
4880−direct
4881−direction
4882−directive
4883−directly
4884−director
4885−directorate
4886−directory
4887−direful
4888−dirge
4889−dirigible
4890−dirk
4891−dirndl
4892−dirt
4893−dirty
4894−disability
4895−disable
4896−disabuse
4897−disadvantage
4898−disaffected
4899−disafforest
4900−disagree
4901−disagreement
4902−disallow
4903−disappear
4904−disappoint
4905−disappointment
4906−disapprobation
4907−disapprove
4908−disarm
4909−disarrange
4910−disarray
4911−disassociate
4912−disaster
4913−disavow
4914−disband
4915−disbelieve
4916−disbud
4917−disburden
4918−disburse
4919−disc
4920−discard
4921−discern
4922−discharge
4923−disciple
4924−disciplinarian
4925−discipline
4926−disclaim
4927−disclose
4928−disco
4929−discolour
4930−discomfit
4931−discomfort
4932−discommode
4933−discompose
4934−disconcert
4935−disconnect
4936−disconsolate
4937−discontent
4938−discontinue
4939−discontinuous
4940−discord
4941−discotheque
4942−discount
4943−discountenance
4944−discourage
4945−discourse
4946−discourteous
4947−discover
4948−discovery
4949−discredit
4950−discreet
4951−discrepancy
4952−discrete
4953−discretion
4954−discriminate
4955−discrimination
4956−discursive
4957−discus
4958−discuss
4959−discussion
4960−disdain
4961−disease
4962−disembark
4963−disembarrass
4964−disembody
4965−disembowel
4966−disenchant
4967−disencumber
4968−disenfranchise
4969−disengage
4970−disentangle
4971−disequilibrium
4972−disestablish
4973−disfavour
4974−disfigure
4975−disforest
4976−disfranchise
4977−disgorge
4978−disgrace
4979−disgruntled
4980−disguise
4981−disgust
4982−dish
4983−dishabille
4984−disharmony
4985−dishearten
4986−dishevelled
4987−dishonest
4988−dishonour
4989−disillusion
4990−disincentive
4991−disinclination
4992−disincline
4993−disinfect
4994−disinfest
4995−disinflation
4996−disingenuous
4997−disinherit
4998−disintegrate
4999−disinter

13767 more lines aren’t shown here.

sys/games/lib/fortunes+0−5235
@@ -1,5235 +0,0 @@
1−login: 
2− case '\7': *((char *)(384*1024L+062)) = 2; /* beep */
3− Welcome to VAX/VMS Version 1.60
4− ON ENDFILE(SYSIN) GO TO ADATHIBA; /* FILE-VEGE VIZSGALATA */
5− Tape dump of all filesystems taken this afternoon.
6−"Analysis" is "design" spelled backwards.
7−"RULE 7: Option arguments cannot be optional." Sys V Interface p 343.
8−"Sound advice" is usually mostly sound with not much advice.
9−"The Dresser," first a play, then a movie, then AT&T headquarters.
10−"The more you drive ... the less intelligent you are." -- Miller, in Repo Man
11−"x.c", line 1: cannot recover from earlier errors: goodbye!
12−#(cat probably won't work on 8 bit files, you will have to use a simpler filter)
13−$! nulled, predecessor circle
14−$3,000,000
15−%-W-NORML Normal Successful Completion
16−'Tis a gross error, held in schools, That Fortune always favours fools. - John Gay.
17−'Tis better playing with a lion's whelp,/Than with an old one dying.
18−'Tis nobler in the mind to Look Things Up than to Pull Them Out Of The Air.
19−(^|[ (,;])(([Jj]ul[^ ]* *|(07|7)/)0*5)([^0123456789]|$)
20−* UNIX is a Trademark of Bell Laboratories.
21−*** LGP ERROR ***: Initialize -- Cannot initialize graphics hardware device.
22−*** REPLACE THIS LINE WITH YOUR MESSAGE ***
23−-1: No code table for op: ++post
24−...and on the seventh day, He exited from append mode.
25−/usr/games/fortune: not found
26−/usr/news/gotcha
27−1 bulls, 3 cows
28−127 now in the unregulated subsidiary; see /usr/news/btl-split
29−2 is always smaller than 3, even for large values of 2.
30−2 lacks generality in a way that 1 doesn't.
31−23. ... r-q1
32−355/113 -- not the famous irrational number PI, but an incredible simulation.
33−4.2BSD is like a nightmare about Tenex. - Geoff Collyer
34−4.2BSD may not be a complete disaster, but it does a good job of emulating one.
35−55mph -- It's not a good idea, it's just the law.
36−: is not an identifier
37−A 10.0-szer 0.1 sohasem 1.0!
38−A 6-char limit is like a 6-inch trout: throw it back.
39−A 6-char limit is like night.
40−A Cray is the best machine for simulating the performance of a Cray.
41−A Point is a pair of shorts.
42−A Smith and Wesson beats four aces.
43−A bad workman quarrels with his tools.
44−A big book is a big nuisance. - Callimachus, librarian of Alexandria
45−A billion here, a billion there; soon you're talking real money. -E. Dirksen
46−A bird in hand is safer than one overhead.
47−A bird in the hand is worth what it will bring.
48−A block grant is a nice terminal, but it will keep you awake until noon.
49−A block grant is a solid mass of money surrounded on all sides by governors.
50−A chicken is just an egg's way of making more eggs.
51−A closed mouth gathers no foot.
52−A conservative is one who is too cowardly to fight and too fat to run.
53−A consistent indentation style is the hobgoblin of little minds.
54−A couch is as good as a chair.
55−A coward is one who in a perilous emergency thinks with his legs.
56−A critic is a legless man who teaches running.
57−A day for firm decisions!!!!! Or is it?
58−A day without sunshine is like night.
59−A duck with three wings and a loaf of bread is brother to the sun god.
60−A duck with three wings and a loaf of bread is brother to the turkey.
61−A fly by night leaves no shadow beyond a doubt.
62−A fool and his money stabilize the economy.
63−A foolish consistency is the hobgoblin of little minds.
64−A furore Normanorum libera nos, O Domine!
65−A game, a teaching aid, a sport, and a piece of art. -Erno Rubik
66−A gentleman is one who is never rude unintentionally. -Noel Coward
67−A good memory does not equal pale ink.
68−A good plan today is better than a perfect plan tomorrow.
69−A goodly apple rotten at the heart:/Oh, what a goodly outside falsehood hath!
70−A hacker does for love what others would not do for money.
71−A homeowner's reach should exceed his grasp, or what's a weekend for?
72−A hydrogen bomb doesn't care how brave you are.
73−A hypothesis is an opinion that you are trying to prove true.
74−A journey of a thousand miles begins with a cash advance from Sam.
75−A king's castle is his home.
76−A liberal is one too open-minded to take his own side in an argument.
77−A lone dime always gets the number nearly right.
78−A man does not attain the status of Galileo merely because he is persecuted; he must also be right. -Stephen Jay Gould
79−A man must destroy himself before others can destroy him. -Mong Tse
80−A man who fishes for marlin in ponds will put his money in Etruscan bonds.
81−A man who turns green has eschewed protein.
82−A man with 3 wings and a dictionary is cousin to the turkey.
83−A man without a faith is like a fish without a bicycle.
84−A megabyte here, a megabyte there, and pretty soon you're talking real power.
85−A megaflop is a failure of gigantic proportions.
86−A mighty maze! but not without a plan. -Pope
87−A more wretched hive of scum and villainy: not found.
88−A movie studio is the best toy a boy ever had. -Orson Welles
89−A penny saved is a political breakthrough.
90−A penny saved is ridiculous.
91−A penny saved kills your career in the Pentagon.
92−A philosopher does not need a torch to gather glow-worms by at mid-day. -- Earnest Bramah
93−A plague o' both your houses! They have made worms' meat of me.
94−A plucked goose doesn't lay golden eggs.
95−A poet who reads his verse in public may have other nasty habits.
96−A professor is one who talks in someone else's sleep.
97−A radical is a person with both feet firmly planted in the air.
98−A real Initiation never ends. -Aleister Crowley
99−A really busy person never knows how much he weighs. -Edgar Watson Howe
100−A recently completed trial proved TOAD Generic 1 to be reliable, user-friendly, and convenient.
101−A resort area will be part of your next holiday plans
102−A rolling stone gathers momentum.
103−A rose by any other name would still have thorns.
104−A sharp tongue is the only edge tool that grows keener with constant use. -W. Irving
105−A song in time is worth a dime.
106−A stitch in time keeps your tu-tu from becoming a four-four.
107−A system programmer is someone who debugs his programs with an oscilloscope.
108−A theory is better than an explanation.
109−A thousand throats may be slit in one night by a running man.
110−A tree is best measured when it is down.
111−A truly wise man never plays leapfrog with a Unicorn.
112−A twisting road will take you to Warsaw, but you won't be bored.
113−A u.f.o. closely encountered is no longer a u.f.o.
114−A victory is the greatest tragedy in the world - except a defeat. -Wellington
115−A watched terminal never prints.
116−A wise man never tries to warm himself in front of a painting of a fire.
117−A witty saying means nothing. -Voltaire
118−A woman is only a woman, but a good cigar is a smoke. -Rudyard Kipling
119−A578 Your FLP overflows into your KBUF.
120−AAAOO OOZOR AZZAZ ZAIEO AZAEI IIOZA KHOEO OOYTH OEAZA EAOOZ AKHOZ AKHEY THXAA LETHX KH
121−Ablata at alba.
122−Abortion and suicide are hereditary only if you prevent them.
123−About all some parents accomplish in life is either illegal, immoral or fattening.
124−About all some parents accomplish in life is to send a child to Harvard.
125−About the only thing on a farm that has an easy time is the dog.
126−Absence is better than a cure.
127−Absinthe makes the heart grow fonder.
128−According to the latest official figures, 43% of all statistics are worthless.
129−Accounting software is structured as a set of tools that can be used to build accounting systems.
130−Ad pulchritudinem tria requiruntur; integritas, consonantia, claritas. -Aquinas
131−Admiration is our polite recognition of another's resemblance to ourselves.
132−After 24 hours, corpses and guests smell bad.
133−After all, a murderer is only an extroverted suicide.
134−Afternoon very favorable for romance. Try a single person for a change.
135−Again, and strongly, undress the sheep. It is getting to visitors.
136−All articles that coruscate with resplendence are not truly aurifers.
137−All dare to write, who can or cannot read. -Horace, `Epistles', Book II
138−All my men wear badges, or they wear nothing at all.
139−All of the bridges between our today and our yesteryear have been burnt.
140−All of these futures having been sold, this fortune appears as a matter of record only.
141−All syllogisms have three parts; therefore this is not a syllogism.
142−All that does not glitter is not not-gold.
143−All the ethics in Hollywood can be rolled up and fit into a gnat's navel.
144−All the good ones are taken.
145−All the great men are dead and I'm not feeling too well myself.
146−All things considered, life is 9-to-5 against.
147−All things that are, are lights.
148−All you need to know is in the manual.
149−Almost all good computer programs contain at least one random-number generator.
150−Always keep a record of data. It indicates you've been working.
151−Always make water when you can. -Wellington
152−America's best buy for a dime is a telephone call to the right person.
153−An Austrian army, awfully arrayed, Boldly by battery besieged Belgrade.
154−An airplane is in your future.
155−An artist is never ahead of his time, but most people are far behind theirs. - Varese
156−An asylum for the sane would be empty in America.
157−An atheist is a man with no invisible means of support.
158−An elephant is a mouse built to government specifications.
159−An elephant is a mouse with an operating system.
160−An idle mind is worth two in the bush.
161−An oscilloscope is what cavemen used to debug fire. -Jim Veres
162−An ounce of application is worth a ton of abstraction.
163−And I alone am returned to wag the tail.
164−And malt does more than Milton can/to justify God's ways to man -A.E. Housman
165−And so to bed.
166−Androgyny recapitulates philately.
167−Another good night not to sleep in a eucalyptus tree.
168−Any change or reform you make is going to have consequences you don't like.
169−Any clod can have the facts, but having opinions is an *art*. -Chas. McCabe
170−Any country with "democratic" in the title isn't.
171−Any fool can paint a picture, but it takes a wise person to be able to sell it.
172−Any man's speeding ticket on the Interstate diminishes me, for I am involved in mankind.
173−Any small object that is accidentally dropped will hide under a larger object.
174−Any sufficiently advanced technology is indistinguishable from a rigged demo.
175−Any sufficiently advanced technology is indistinguishable from magic. -Clarke
176−Anyone can win, unless there happens to be a second entry.
177−Anyone who buys Wisconsin cheese is a traitor to mankind! -J. Pournelle
178−Anyone who understands my music will never be unhappy again. -L. Van Beethoven
179−Anyone's life is incomplete unless they are, in some smaller or larger way, saving the world.
180−Anything good in life is either illegal, immoral or fattening.
181−Arabic is a language, Persian is a sweetmeat, and Turkish is an art.
182−Arabic is a mystery -- love is just a crock.
183−Are we not men?
184−Are you kidding?
185−Are you sure you want a two dimensional array?
186−Aren't you glad his name wasn't Alexander Graham Klaxon?
187−Aries -- this is your lucky day!
188−Art is merely cheese made visible.
189−Artistic ventures highlighted. Rob a museum.
190−As above, so below.
191−As goatherd learns his trade by goat, so writer learns his trade by wrote.
192−As of Tuesday, C will be flushed in favor of COBOL. Please update all programs.
193−Assassination is the extreme form of censorship.
194−At the feast of souls failure is always the guest of honor.
195−Atomic compare and exchange. These sequences are not actually atomic [⋯]. However, they are very close to atomic, [⋯] LinuxThreads has been using these sequences for many years.
196−Attend winter sheep meetings. Learning never ends!
197−Auribus teneo lupum.
198−Automating a mess yields an automated mess. -Michael Hammer
199−Ave discordia.
200−Avoid a hasty decision.
201−Avoid reality at all costs.
202−Away put your weapon! I mean you no harm.
203−BLISS is ignorance.
204−Bad taste is timeless.
205−Ban the bomb. Save the world for conventional warfare.
206−Bank error in your favor. Collect $200.
207−Basic is like doing arithmetic with Roman numerals. - MD McIlroy
208−Be sure to evaluate the bird-hand/bush ratio.
209−Be the sea, and see me be.
210−Beauty is only sin deep. H H Munro
211−Beauty is only skin deep, but ugly goes clean to the bone.
212−Beauty times brains equals a constant.
213−Becoming an overnight success usually takes years.
214−Been Transferred Lately?
215−Better be right or your big venture goes wrong. -Resistor color code mnemonic
216−Better to have failed your Wasserman than never to have loved at all.
217−Between the idea and the reality, between the motion and the act falls the shadow.
218−Beware -- local customs vary. Check with a native before going into the jungle.
219−Beware of a dark-haired man with a loud tie.
220−Beware of low-flying butterflies.
221−Beware the foot of Nessus!
222−Beware: the light at the end of the tunnel may be New Jersey.
223−Beyond a certain point, the whole universe becomes a continuous Initiation.
224−Bigamy is having one spouse too many. Monogamy is the same.
225−Biggus Diggus wants YOU.
226−Bignose from Winnetka.
227−Blessed St. Leibowitz, let them keep on dreamin' down there...
228−Blessed are the meek for they shall inhibit the earth.
229−Blessed are they who Go Around in Circles, for they Shall be Known as Wheels.
230−Bosses never realize that a bottle neck is always at the top.
231−Bourne again.
232−Brain fried -- core dumped
233−Brashith Alhim
234−Bring your wife or husband and pink slip for the best trade-in deal in town.
235−Bubble bubble, toil and trouble; cast that float into a double.
236−Buick offers inbred american quality. -TV ad
237−Build a better mousetrap, and nature will build a better mouse.
238−Build it so that even a fool can use it, and only a fool will want to use it.
239−Bus error -- core dumped
240−But he who kisses the joy as it flies/Lives in Eternity's sunrise. -Wm. Blake
241−But many are not capable of a firm persuasion of anything. -Wm. Blake
242−But you'll never become a rhinoceros...you haven't got the vocation!
243−But, Siriusly...
244−By failing to prepare, you are preparing to fail.
245−By omnibus I traveled to Brooklyn.
246−By the pricking of my thumbs,/Something wicked this way comes.
247−C'est CHouette. Swiss bumper sticker
248−C'est dommage, mais c'est vrai.
249−C'est magnifique, mais ce n'est pas Unix. -Henry Spencer
250−CB is a great place to work. There are so many good going away parties.
251−CB is a many gendered thing.
252−California is a fine place to live if you happen to be an orange. - Fred Allen
253−Campus Crusade for Cthulhu -- It found me.
254−Can all this just be an accident? Or could there be some alien intelligence behind it?
255−Can tomorrow be more than just the end of today?
256−Cannot fork -- try again.
257−Capitalism is indeed obsessed with money, but Marxism is obsessed with Marxism.
258−Captain Clark welcomes you aboard.
259−Caught in --More-- loop.
260−Caution -- be sure brain is engaged before putting mouth in gear.
261−Caution: Do not view laser light with remaining eye.
262−Caution: breathing may be hazardous to your health.
263−Celebrate Hannibal Day this year. Take an elephant to lunch.
264−Celibacy is not hereditary.
265−Center 1127 -- It's not just a job, it's an adventure!
266−Center meeting at 4pm in 2C-543
267−Centran manuals are available in 2B-515.
268−Charlie don't surf.
269−Children are hereditary: if your parents didn't have any, neither will you.
270−Clothes make the man. Naked people have little or no influence on society.
271−Club sandwiches, not baby seals.
272−Cocaine is nature's way of saying you make too much money.
273−Cogito Ergo Spud.
274−Cogito cogito ergo cogito sum.
275−Colorless green ideas sleep furiously.
276−Communication is only possible between equals.
277−Computers are not intelligent. They only think they are.
278−Consistency is always easier to defend than correctness.
279−Constants aren't. Variables don't. LISP does. Functions won't. Bytes do.
280−Contains no kung fu, car chases or decapitations.
281−Continental Life. Why do you ask?
282−Convictions cause convicts -- what you believe imprisons you.
283−Core Error - Bus Dumped
284−Could not open 2147478952 framebuffers.
285−Courage is something you can never totally own or totally lose.
286−Cowards die many times before their deaths;/The valiant never taste of death but once.
287−Crazee Edeee, his prices are INSANE!!!
288−Creativity is no substitute for knowing what you are doing.
289−Creditors have much better memories than debtors.
290−Critics are like eunuchs in a harem: they know how it's done, they've seen it done every day, but they're unable to do it themselves. -Brendan Behan
291−Cthulhu Saves! ... in case He's hungry later.
292−Dames is like streetcars -- The oceans is full of 'em. -Archie Bunker
293−Dames lie about anything - just for practice. -Raymond Chandler
294−Damn it, i gotta get outta here!
295−Dangerous knowledge is a little thing.
296−Data potato, du wop du wop.
297−Day of inquiry. You will be subpoenaed.
298−De minimis non curat lex.
299−Death is nature's way of telling you to slow down.
300−Death to all fanatics!
301−Deep down, we all need that escape velocity. -Steven Spielberg.
302−Democracy is also a form of worship. It is the worship of Jackals by Jackasses.
303−Department meeting in 3 minutes.
304−Deprive a mirror of its silver and even the Czar won't see his face.
305−Der Herrgott wurfelt nicht. -A. Einstein
306−Did you know ... that no-one ever reads these things?
307−Did you know that clones never use mirrors?
308−Die ich rief, die Geister, / Werd ich nun nicht los.
309−Die: to stop sinning suddenly.
310−Dieux! Un monstre hideux. En hurlant. Nous poursuit.
311−Diplomacy is the art of saying "nice doggy" until you can find a rock.
312−Disco delenda est.
313−Disk crisis, please clean up!
314−Disobedience was Man's Original Virtue. -Oscar Wilde.
315−Distrust yourself, and sleep before you fight. 'Tis not too late tomorrow to be brave. - J. Armstrong.
316−Ditat Deus.
317−Do not believe in miracles -- rely on them.
318−Do not clog intellect's sluices with bits of knowledge of questionable uses.
319−Do not confuse boredom with security.
320−Do not confuse effort with work.
321−Do not drink coffee in early A.M. It will keep you awake until noon.
322−Do not go gentle into that good night/Rage, rage against the dying of the light
323−Do not meddle in the affairs of troff; it is subtle and quick to anger.
324−Do not meddle in the affairs of wizards: it makes them soggy and hard to light.
325−Do not meddle in the affairs of wizards: they are subtle and quick to anger.
326−Do not meddle in the mouth.
327−Do not sleep in a eucalyptus tree tonight.
328−Do not take life too seriously; you will never get out if it alive.
329−Do not throw butts in the urinal: it makes them soggy and hard to light.
330−Do not throw butts in the urinal: they are subtle and quick to anger.
331−Do not underestimate the power of the Force.
332−Do not use the blue keys on this terminal.
333−Do something unusual today. Pay a bill.
334−Do what comes naturally now. Seethe and fume and throw a tantrum.
335−Do what thou wilt shall be the whole of the law.
336−Does George know what he's got here? -Steven Spielberg.
337−Does a firm persuasion that a thing is so make it so? -Wm. Blake
338−Does the early bird enjoy the worm as much as the late bird enjoys the sleep?
339−Don't be overly suspicious where it's not warranted.
340−Don't believe everything you hear or anything you say.
341−Don't call me a mindless philosopher, you overweight glob of grease.
342−Don't commute, communicate.
343−Don't conscience-stricken before they're hatched.
344−Don't eat yellow snow.
345−Don't feed the bats tonight.
346−Don't force it, use a bigger hammer.
347−Don't forget to run "make depend"
348−Don't get mad, make book.
349−Don't go surfing in South Dakota for a while.
350−Don't hate yourself in the morning -- sleep till noon.
351−Don't kiss an elephant on the lips today.
352−Don't let your thoughts get in a rut. The knife which spreads may also cut.
353−Don't lie if you don't have to. -Leo Szilard
354−Don't look back -- something may be gaining on you. -Satchel Paige.
355−Don't play games with me. You weren't on any mercy mission this time.
356−Don't put a loaded rifle on the stage unless someone intends to fire it.
357−Don't rely on your nose -- TEST ATMOSPHERE!
358−Don't speak about Time, until you have spoken to him.
359−Don't tell any big lies today. Small ones can be just as effective.
360−Don't try to have the last word. You might get it.
361−Don't try to out-weird me, I get stranger things than you free with my breakfast cereal.
362−Don't type so hard.
363−Don't vote -- it only encourages them.
364−Don't worry -- dat mine, it can't hurt us -- it's one of ours. -Eccles
365−Don't worry if it doesn't work right; if everything did, you'd be out of a job.
366−Don't worry, it's not loaded.
367−Don't worry, they couldn't hit an elephant at this dist
368−Don't you feel more like you do now than you did when you came in?
369−Don't you have anything better to do with your time?
370−Down with categorical imperative!
371−Dreams are free, but there's a small charge for alterations.
372−Dreams are free, but you get soaked on the connect time.
373−Drive defensively, buy a tank.
374−Ducking for apples. Change one letter and it's the story of my life. _ Dorothy Parker
375−Dump time is unreasonable
376−During 1986, UNIX will dominate the low end. J. Scanlon
377−Dyslexics of the world, untie!
378−E Pluribus Unix.
379−E Unibus Plurum.
380−E pur si muove.
381−ERROR CREEPOUT HAS BEGUN
382−EVACUATION ROUTE ---->
383−Each man's death diminishes me for I am involved in Humanity. -John Donne
384−Easy for you to type, I have to do all the work.
385−Eat snart foobs. -Unknown Jerome
386−Economic analysts say that while the economy may be slowing, it is not fizzling out.
387−Edinburgh is the Reykjavik of the South.
388−Ego sum ens omnipotens.
389−Eileen L. Behr has translated her skill in public speaking into a successful career selling capacitors.
390−Either I'm dead or my watch has stopped. -Groucho Marx' last words
391−Either we are alone or we are not. Either way is mind-boggling.
392−Eleemosynary deeds have their incipience intramurally.
393−English is a stretch language; one size fits all. -W. Safire
394−Eschew the implement of correction and vitiate the scion.
395−Espanol tiene demasiada mucha grammatica.
396−Even a cabbage may look at a king.
397−Even a hawk is an eagle among crows.
398−Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley
399−Even paranoia can sometimes be taken to extremes.
400−Even the boldest zebra fears the hungry lion.
401−Even the simplest solution is bound to have something wrong with it.
402−Even the smallest candle burns brighter in the dark.
403−Even the thousand-zloty note can't tapdance.
404−Even these days, it's not as easy to go crazy as you think.
405−Ever see what ratfor does on a syntax error in a for loop?
406−Ever wake up feeling like a null pointer? -Allan Pratt
407−Every absurdity has a champion to defend it.
408−Every cloud has a silver lining; you should have sold it, and bought titanium.
409−Every day, thousands of housewives pick up speed.
410−Every excess becomes a vice.
411−Every good subversive does it for fun. -Rich Rosen
412−Every law creates a whole new criminal class overnight.
413−Every little picofarad has a nanohenry all its own.
414−Every purchase has its price.
415−Every solution breeds new problems.
416−Every time you make something foolproof, along comes a better class of fool.
417−Everybody should believe in something -- I believe I'll have another drink.
418−Everything breaks down.
419−Everything east of the San Andreas Fault will eventually plunge into the ocean.
420−Everything is funny so long as it is happening to someone else. -Will Rogers
421−Everything should be as simple as possible, but no simpler. - A. Einstein
422−Everything takes longer than you think.
423−Everything you know is wrong.
424−Everything's been said before, but nobody's listening, so keep repeating.
425−Ewige Blumenkraft.
426−Excellent day for drinking heavily. Spike the office water cooler.
427−Excellent day to have a rotten day.
428−Excellent time to become a missing person.
429−Executive ability is in your make-up.
430−Exercise is the Yuppie version of bulemia.
431−Exhibition will continue to decline and ultimately lead to other sources of entertainment.
432−Expansion means complexity; and complexity decay.
433−Expected arrival date is presently unknown. -Dave Kristol
434−Experience varies directly with the equipment ruined.
435−Explicit liber viri elephantini.
436−External Security:
437−FORTRAN 8X combines the simplicity of PL/I and the parsimony of ADA. -S Feldman
438−Fact without theory is trivia, theory without fact is bullshit.
439−Facta, non verba -- et verbum caro factus est.
440−Facta, non verba.
441−Fairness? Decency? How can you expect fairness and decency on a planet of sleeping people?
442−Far duller than a serpent's tooth it is to spend a quiet youth.
443−Far too noisy, my dear Mozart. Far too many notes. -Emperor Ferdinand.
444−Favor negative lobes.
445−Fear is failure and the forerunner of failure.
446−Fear not, the end of the world isn't until next week.
447−Few things are harder to put up with than the annoyance of a good example.
448−Fiat lux.
449−Fiat voluntas tua.
450−Fill what's empty; empty what's full; scratch where it itches. -Alice Roosevelt Longworth
451−Find the enemy and shoot him down; everything else is rubbish. -M. von Richthofen
452−Fine day to throw a party. Throw him as far as you can.
453−Fine day to work off excess energy. Steal something heavy.
454−First there is a mountain, then there is no mountain, then there is.
455−First things first. Why not send for the Nazis right now.
456−Fleas can be taught nearly anything that a congressperson can.
457−Flee at once, all is discovered.
458−Flight 23 is down in the Bermuda Triangle.
459−Florida is the "flea and tick capital of America."
460−Fnord.
461−For a good time, call 8367-3100.
462−For every action there is an equal and opposite government program.
463−For me, UNIX is a way of being. -Armando P. Stettner
464−For people who like that kind of book, that is the kind of book they will like.
465−Forget it, Jake...it's Chinatown.
466−Forsan et haec olim meminisse juvabit.
467−Fortis fortuna adiuvat. - Terence
468−Fortran est; non potest legi.
469−Fortunate are they who can laugh at themselves; they will never want for amusement.
470−Fortune, good night, smile once more, turn thy wheel! - King Lear II.ii.180
471−Fortunes ... come tumbling into some men's laps. - Francis Bacon.
472−Frankly, I'd rather be in Philadelphia.
473−Freedom is the right to be our own potty little selves. -G. K. Chesterton
474−Freedom of incrustations of grime is contiguous with rectitude.
475−Friends come and go, but enemies accumulate.
476−Fritter and waste the hours in an offhand way.
477−From EXPLMY: Serious internal error, check the error code in the documentation of VRFYMY.
478−Future looks spotty. You will spill soup in late evening.
479−Gaffer's tape, like The Force, has a light and a dark side and binds the universe together.
480−Gallium Arsenide is the material of the future and it always will be.
481−Generalizations are useful. The work contained in them can be reckoned as labor and therefore can create value. -G.W. Hegel
482−Generosity and perfection are your everlasting goals.
483−Genius is the talent of a person who is dead.
484−Gentlemen, you can't fight here. This is the war room.
485−Get your boots on, 'cause we're gunna go in DEEP!
486−Give me a rock, paper and scissors and I will move the world. CCFestoon
487−Give me a sleeping pill and tell me your troubles.
488−Give your child mental blocks for Christmas.
489−Given enough inside information and unlimited credit, you've got to go broke.
490−Go directly to jail. Do not pass Go, do not collect $200.
491−Go out and see what the real world has to offer -Gerry Todd
492−Go suck on an infinite tube.
493−God does not play dice.
494−God gives us relatives; thank goodness we can choose our friends.
495−God is in the rock too -- in the rock!
496−God isn't dead, he just couldn't find a parking place.
497−God made the integers; all else is the work of Man.
498−God not only plays dice with the universe, He loads the dice too.
499−Gods! A hideous beast, baying is pursuing us!
500−Golden lads and girls all must,/Like chimney sweepers, come to dust.
501−Good Americans, when they die, go to Paris. - Thomas Appleton.
502−Good Rule: Don't put anything in your mouth labeled "HARMFUL IF SWALLOWED"
503−Good day for a change of scene. Repaper the bedroom wall.
504−Good day for flaming at floyd!trb.
505−Good day for overcoming obstacles. Try a steeplechase.
506−Good day to avoid cops. Crawl to work.
507−Good day to do the unexpected: write some documentation.
508−Good day to let down old friends who need help.
509−Good day to write a purchase requisition for a 747.
510−Good fish get dull but sex is always fun. -- Mehinaku proverb
511−Good health is just the slowest, most lingering way of dying.
512−Good intentions don't mean anything unless they can deliver.
513−Good manners and bad breath get you nowhere
514−Good news. Ten weeks from Friday will be a pretty good day.
515−Gort! Klaatu barada...uh...uh...
516−Government expands to absorb all available revenue and then some.
517−Government is just Anarchy's way of making more anarchy.
518−Graecum est; non potest legi.
519−Great shot, kid. That was one in a million.
520−Great warrior? Heh-heh-heh. Wars do not make one great.
521−Green light in A.M. for new projects. Red light in P.M. for traffic tickets.
522−Growth itself becomes the only moral end. -John Dewey
523−Guns don't kill detectives -- love does.
524−Ha! You killed my husband, Sam. Be kind to me.
525−Had Cleopatra's nose been shorter, the whole history of the world would have been different. - Pascal
526−Hail to the sun god/He sure is a fun god/Ra! Ra! Ra!
527−Half Moon tonight. (At least it's better than no Moon at all.)
528−Hang by your pseudopod, write if you find a warm rich planet ripe for conquest.
529−Hang in there, hammock-nose.
530−Hangover is the wrath of the grapes.
531−Have a nice diurnal anomaly.
532−Have you done your Christmas chopping yet? -anon. White House Advisor 12/24/81
533−Have you hugged my T-shirt today?
534−He can't think without his hat.
535−He cried at all his own weddings, and with reason.
536−He gave her a look that you could have poured on a waffle.
537−He is no lawyer who cannot take two sides.
538−He is truly wise who gains wisdom from another's mishap.
539−He is winding the watch of his wit; by and by it will strike.
540−He looked at me as if I was a side dish he hadn't ordered.
541−He missed an invaluable opportunity to hold his tongue.
542−He serves the state best who opposes it most. -Thoreau
543−He that laugheth in the face of death haveth the last laugh.
544−He thinks by infection, catching an opinion like a cold.
545−He was al coltissh, ful of ragerye,/And ful of jargon as a flekke pye. -Chaucer
546−He was so narrow-minded he could see through a keyhole with two eyes.
547−He who binds himself to a joy/Does the winged life destroy. -Wm. Blake
548−He who has a shady past knows that nice guys finish last.
549−He who has imagination without learning has wings but no feet.
550−He who has science and art has religion. -Goethe
551−He who hesitates is last.
552−He who hesitates is scrap metal.
553−He who hesitates is sometimes saved.
554−He who invents adages for others to peruse takes along rowboat when going on cruise.
555−He who keeps his nose to the grindstone, has a flat face.
556−He who laughs last is a little slow on the uptake.
557−He who laughs, lasts.
558−He who listens last is the last one listening.
559−He who makes a beast of himself gets rid of the pain of being a man. -H.S. Thompson
560−He who spends a storm beneath a tree, takes life with a grain of TNT.
561−He who trains his tongue to quote from learned sages will be known far and wide as a smartass.
562−He who wears belt and suspenders needs tighter belt.
563−Help a swallow land at Capistrano.
564−Help conquer the IQ shortage: worry less and think more.
565−Help me, i'm a prisoner in a chinese computer terminal!
566−Hey, I've got it -- let's put on a show!
567−Hi, this is Ken. What's the root password?
568−Hindsight is an exact science.
569−His heart was yours from the first moment that you met.
570−His money is twice tainted: 'taint yours and 'taint mine.
571−History is a race between education and catastrophe. -H. G. Wells
572−Hit space to start
573−Hodie tempum scriptire in Latinum non habeo. Cras epistlum submissibo.
574−Home is the place where, when you have to go there, they have to take you in.
575−Home is where / is.
576−Honi soit la vache qui rit.
577−Hop before you skip.
578−Horse sense is the thing a horse has which keeps it from betting on people.
579−How I want a drink, alcoholic of course, after the chapters involving quantum mechanics.
580−How can I take an interest in my work when I don't like it?
581−How can you work when the system's so crowded?
582−How did the Universe manage to go bang in such an unreasonable way? -PCW Davies
583−How do I love thee? Hand me my calculator...
584−How is it far, if you can think of it?
585−How long you live has nothing to do with how long you are going to be dead.
586−How sharper than a child's tooth it is to have a thankless serpent.
587−How sharper than a serpent's tooth it is to have a thankless child.
588−How the elephant got into my pyjamas I'll never know. -Marx, Animal Crackers
589−How wonderful opera would be if there were no singers.
590−How you look depends on where you go.
591−Human beings are the only animals of which I am thoroughly and cravenly afraid.
592−Human kind cannot bear very much reality. -T.S. Eliot
593−Hypocrisy is the tribute vice pays to virtue.
594−Hypothesize and test.
595−I am Magnus. You are registered in my memory banks...
596−I am a high-pressure guy, and I didn't take this job to conduct a going-out-of-business sale. - A.A. Penzias
597−I am free of the wheel of Maya; I am dead to the dance of life.
598−I am large; I contain multitudes.
599−I am the Supreme Being. I'm not entirely dim.
600−I am the beast, I am the Word of the Aeon...I am a hell of a Holy Guru.
601−I am the wandering glitch -- catch me if you can.
602−I can call spirits from the vasty deep./Why, so can I, or so can any man.
603−I can resist everything except temptation. -Oscar Wilde.
604−I can't decide whether to throw you overboard or just change the way you look.
605−I cannot teach him. The boy has no patience.
606−I contradict myself? Very well, then: I contradict myself. I am large.
607−I dinna believe she'll hold up much longer, Captin.
608−I do not sketch or design a work, I merely begin. -Joan Miro
609−I don't even know what street Canada is on. - Al Capone
610−I don't have a moral plan... I'm a Canadian. -David Cronenberg
611−I don't like to walk, and I don't like to paddle. -James Watt
612−I don't love you any more since you ate my dog.
613−I don't mind your thinking slowly; i mind your publishing faster than you think. -W. Pauli
614−I give presents to the mother, but I think of the daughter.
615−I hate programs that chdir on you - Boyd Roberts
616−I have 36 rolls of 5247 for our use in the laser fridge...
617−I have NEVER written a program in C! Narain Gehani
618−I have discovered the art of deceiving diplomats; I tell them the truth and they never believe me. -Cavour
619−I have everything we will need.
620−I have never let my schooling interfere with my educations.
621−I have nothing to say and I am saying it and that is poetry as I need it. -Cage
622−I have the most perfect confidence in your indiscretion.
623−I haven't lost my mind. I've got it backed up on tape somewhere.
624−I hope that there are sour apples in every bushel.
625−I kissed my first cigarette on the herpolhode lying in the invariable plane.
626−I kissed my first cigarette on the stage unless someone intends to fire it.
627−I kissed my first lady and smoked my first cigarette on the same day. I have never had time for tobacco since. -Arturo Toscanini
628−I know nothing. -Ken Thompson
629−I know the difference between real-real and drug-real.
630−I like user-hostile ignorance-based amateur systems.
631−I like work; it fascinates me; I can sit and look at it for hours.
632−I love Pascal ... I'm also into leather.
633−I love the smell of napalm in the morning.
634−I love you.
635−I must have slipped a disk; my pack hurts.
636−I never dringk ... wine. -Bela Lugosi
637−I never refuse. I never contradict. I sometimes forget. -Disraeli
638−I knew it was coming and I still felt as if I'd swallowed a snowcone whole.
639−I regard an original error as better than a borrowed truth. -Merton.
640−I regard an original error as better than no Moon at all.
641−I see no login here!
642−I see only darkness in the crystal ball
643−I sense something -- a presence I haven't felt since....
644−I taught him everything he knows. Now he knows more. -Randal L. Schwartz
645−I thank you from the heart of my bottom.
646−I think Isaac Newton is doing most of the driving right now.
647−I think my spaceship knows which way to go.
648−I think that I shall never see a billboard as lovely as a tree. -Ogden Nash
649−I think; therefore I am confused.
650−I was just going to call you.
651−I will not suffer fools gladly, but I will gladly make fools suffer. -Bimmler
652−I wish I had time to explain dimensional transcendentalism -Dr. Who
653−I wish you humans would leave me alone.
654−I wonder what will happen if I touch these two wires together.
655−I would be perfectly happy being Kepler, [but] I have been Kepler many times over.-B. Mandelbrot
656−I wouldn't let a knight out on a dog like this!
657−I wouldn't marry her to a ten foot Pole.
658−I wouldn't marry him with a ten foot pole.
659−I'd give my right arm to be ambidextrous.
660−I'd rather have a free bottle in front of me than a pre-frontal lobotomy. -Martin Mull
661−I'd rather have my mail delivered by Lockheed than ride in a plane built by the Post Office.
662−I'll eat it if I'm wrong. I mean a potato. - Danny Sleator
663−I'll produce anything that gets high ratings. -Anonymous NBC official
664−I'll smoke when the pope's wife takes the pill.
665−I'm a Hollywood writer; so I put on a sports jacket and take off my brain.
666−I'm free -- and freedom tastes of reality.
667−I'm from the government, and I'm here to help you.
668−I'm prepared for all emergencies but totally unprepared for everyday life.
669−I'm so hip I have difficulty seeing over my pelvis.
670−I'm sorry, but I've made other plans.
671−I've done this before and never had any trouble.
672−I've got a ferret sticking up my nose.
673−ICIKL: DO I = 1 /* BY +1 FELTETELEZESEVEL */ TO 2*N;
674−IOT trap -- core dumped
675−IOT trap -- core melted
676−If A=B and B=C, then A=C, except where void or prohibited by law. -Roy Santoro
677−If Congress must do a painful thing, it must be done in an odd-numbered year.
678−If God could perform the tricks we do, He'd be a happy man.
679−If God had meant Texans to ski, he would have made bullshit white.
680−If God had wanted you to go around nude, He would have given you bigger hands.
681−If God is perfect, why did He create discontinuous functions?
682−If God lived on Earth, people would knock out all His windows.
683−If God meant for Texans to ski, He would have made them a mountain.
684−If God wanted us to have a President, He would have sent us a candidate.
685−If I could remember the names of all these particles I would have been a botanist. -- Enrico Fermi
686−If I had only known, I would have been a locksmith. -Albert Einstein
687−If I had to choose between System V and 4.2, I'd resign. - Peter Honeyman
688−If I owned Texas and Hell, I'd rent out Texas and live in Hell.
689−If I say it's safe to surf this beach, Captain, it's safe to surf this beach.
690−If I should return in my absence, kindly detain me until I get back.
691−If I wanted your opinion, I'd tell it to you. -Samuel Goldwyn
692−If Lincoln were alive today he would be spinning in his grave. -G. Ford
693−If MS/DOS is the only operating system you're ever going to use, then the procedure is simple
694−If a thousand people say a foolish thing, it remains a foolish thing.
695−If all economists were laid end to end, they would not reach a conclusion.
696−If anything can go wrong, it will.
697−If at first you don't succeed, quit; don't be a nut about success.
698−If at first you succeed, try to hide your astonishment.
699−If bankers can count, why do they have eight windows and only four tellers?
700−If butterflies had teeth like tigers they would never make it out of the hangar.
701−If double-bubble inflation did occur, then the shadow world is exponentially uninteresting.
702−If ever I utter an oath again may my soul be blasted to eternal damnation.
703−If everything is coming your way, you're in the wrong lane.
704−If ignorance were cornflakes, you'd be General Mills.
705−If it ain't broke, don't fix it.
706−If it doesn't matter, it does not matter.
707−If it happens, it must be possible.
708−If it isn't like TECO, it's not worth using. -Rae McLellan
709−If it pours before seven, it has rained by eleven.
710−If it were dangerous they would post a sign...
711−If it's boring, turn it off.
712−If it's gratitude you want, get a dog. -P. T. Barnum
713−If it's not broken, don't fix it.
714−If it's not worth doing, it's not worth doing well.
715−If it's worth doing well, it's worth doing.
716−If more is better then too much is just enough.
717−If music be the breakfast food of love, kindly do not disturb until lunch time.
718−If some day it should happen that a victim must be found, I've got a little list, I've got a little list.
719−If the "medium is the message" then the message of low-bandwidth timesharing is "blah". -- Alan Kay
720−If the check is truly in the mail, it is surely made out to someone else.
721−If the coin is heads up don't pick it up.
722−If the experiment works, you must be using the wrong equipment.
723−If the facts do not support the theory, they must be disposed of.
724−If the government doesn't trust the people, why doesn't it elect a new people?
725−If the shoe fits, buy the other one, too.
726−If there are any resources you need to get this job done, just let us know.
727−If there is no God, who pops up the next Kleenex? -Art Hoppe
728−If they gave me a goldfish, I would cook it. -Feng Jicai
729−If time heals all wounds, how come the belly button stays the same?
730−If voting could change the system, it would be against the law.
731−If we turn on the lights fast enough, we'll see what the dark looks like.
732−If we'd all been living in California, we wouldn't have worked at ALL.
733−If you ask how much it is, you can't afford it.
734−If you can't find enough radiation at Ralph's, you can probably do without it.
735−If you can't stand the heat, remove your clothing!
736−If you cannot convince them, confuse them. -Harry S. Truman
737−If you do a job too well, you'll get stuck with it.
738−If you don't care where you are, then you ain't lost.
739−If you don't insist on correct answers, I can make it run as fast as you want.
740−If you don't know where you're going, it doesn't matter how you get there.
741−If you don't like the weather in New England, just wait a few minutes.
742−If you don't pay attention to every little detail, you miss most of the jokes.
743−If you gaze long enough into the abyss, the abyss will gaze back into you.
744−If you grab the bull by the horns, feathers will fly.
745−If you have to lie to someone, it's their fault.
746−If you have to think twice about it, you're wrong.
747−If you have to travel on the Titanic, why not go first class?
748−If you know high class quality merchandise, you know this is CHEAP!
749−If you start now you might finish on time.
750−If you suspect a man, don't employ him.
751−If you take the last cup, make a new pot.
752−If you take the last pot, make a new cup.
753−If you think before you speak the other guy gets his joke in first.
754−If you think big enough, you'll never have to do it.
755−If you think it's hard going to the moon, you should try staying home.
756−If you think last Tuesday was a drag, wait till you see what happens tomorrow!
757−If you want to go somewhere, goto is the best way to get there. K Thompson
758−If you want to have clean ideas, change them like shirts.
759−If you were able to count up to infinity I'll bet you would never get over it.
760−If you're asked to join a parade, don't march behind the elephants.
761−If you're feeling good, don't worry. You'll get over it.
762−If you're not apprehensive then you don't understand the situation.
763−If you're not part of the solution, you're part of the precipitate.
764−If your experiment needs statistics, you ought to have done a better experiment. - E. Rutherford
765−Ignore alien orders.
766−Ignore previous fortune.
767−Ignore the fatal errors. It's O.K.
768−Il faut cultiver son jardins. -Voltaire
769−Illegal Arbitrator - Line 23
770−Illegitimi non carborundum.
771−Immanuel Kant but Kubla Khan.
772−In Africa the tusks are too firmly rooted, but in Alabama the Tuscaloosa.
773−In addition to a yes and a no, the universe contains a maybe. -D. Finkelstein
774−In an evolving universe, who stands still moves backwards.
775−In any society, the correct pronunciation is the dialect that has an army.
776−In case of fire, stand in the hall and shout "Fire!".
777−In challenging a kzin, a simple scream of rage is sufficient.
778−In communism Man exploits Man. In capitalism it's the other way around.
779−In comparison with the ancients, we stand like dwarfs on the shoulders of giants. -Bernard of Chartres
780−In girum imus nocte et consumimur igni.
781−In marriage, as in war, it is permitted to take every advantage of the enemy.
782−In nature there is immediate adjustment but no compulsion. -Chuang Chou
783−In order to make an omelette, you have to break a few cooks.
784−In rebus mathematicis errores quam minimi non sunt contemnendi.
785−In the Unix tradition, vi is intended to be a small tool that does one thing well.
786−In the future, all programmers will be able to use malloc.
787−In the land of the blind the one-eyed man can see across the road and prove it.
788−In the land of the blind, the one-eyed man is king.
789−In the land of the one-eyed men, the blind have to wear glasses.
790−In this world, truth can wait; she's used to it.
791−Incest, like charity, begins at home.
792−Insanity is always the best defense against boredom.
793−Inside every large problem is a small problem struggling to get out. -N. Wirth
794−Intermittent resolutions lack potency. -Robert Silverberg
795−Into each life a little fallout must rain. -Baba Rebop
796−It got to a point where I had to get a haircut or a violin. -F.D.Roosevelt
797−It is a poor judge who cannot award a prize.
798−It is a tale told by an idiot, full of sound and fury, signifying nothing.
799−It is a very sad thing nowadays that there is so little useless information.
800−It is absurd to deny the role of fantasy in even the strictest science. -Lenin
801−It is bad luck to be superstitious. -Andrew W. Mathis
802−It is better to have loved and lost -- much better.
803−It is better to have loved and lost than just to have lost.
804−It is better to kiss an avocado than to get in a fight with an aardvark.
805−It is better to light a single candle than to curse the darkness, except at the Browns Ferry reactor.
806−It is better to rule in Hell than to serve in Heaven. -Milton
807−It is better to wear out than to rust out.
808−It is easier to get forgiveness than permission.
809−It is far better to vote for a loser than to elect one.
810−It is far better to vote for a loser than to elect?
811−It is fruitless to become lachrymal over precipitately departed lacteal fluid.
812−It is hard to sit with the turkeys when you soar with the eagles.
813−It is much easier to suggest solutions when you know nothing about the problem.
814−It is the business of the future to be dangerous. -Hawkwind
815−It is the wise bird who builds her nest in a tree.
816−It is useless to put on your brakes when you're upside down. -Paul Newman
817−It seems like the less a statesman amounts to, the more he loves the flag.
818−It seems to make an auto driver mad if he misses you.
819−It steam-engines when it becomes steam-engine time. -Charles Fort
820−It takes approximately two minutes to reposition the continents from one geological era to another.
821−It was a book to kill time for those who liked it better dead.
822−It works better if you plug it in.
823−It would appear that even BTL employees put their pants on one leg at a time.
824−It would be wise to cut expectations in half.
825−It's 5 o'clock. Do you know where your files are?
826−It's Your Environment -- Use It Up!
827−It's a hardware problem.
828−It's a sad woman who buys her own perfume.
829−It's a small world, but I'd hate to have to paint it.
830−It's a software problem.
831−It's a useless but absolutely vital precaution.
832−It's an empty head that wears a hairpiece. - Pauline Kael
833−It's business doing pleasure with you.
834−It's clever, but is it art?
835−It's deja vu all over again.
836−It's difficult to explain Kleenex to an aborigine.
837−It's earlier than you think.
838−It's funny how they work so well, even when they're not appropriate.
839−It's hard to be humble when you're perfect.
840−It's hard to be mellow when you bite your nails.
841−It's hard to be mellow when you can't stand up.
842−It's hard to love someone who looks down on you because your hands get bloody protecting him.
843−It's just a silly native superstition.
844−It's later than you think.
845−It's lonely at the top, but it's lonelier at the bottom.
846−It's morally wrong to allow suckers to keep their money.
847−It's not Camelot, but it's not Cleveland, either. -Boston Mayor Kevin White
848−It's not a car, it's a Volkswagen.
849−It's not cool enough for the eighties.
850−It's not easy to play the clown when you've got to run the whole circus.
851−It's not my fault -- it's a mechanical problem!
852−It's not my fault!
853−It's not reality that's important, but how you perceive things.
854−It's not reality that's important, it's how you perceive things.
855−It's not the time between the takes that takes the time - it's changing your mind between the takes that takes the time. -Stage Dept.
856−It's not the time it takes to take the takes that takes the time, it's the time it takes between the takes that takes the time. -S. Spielberg
857−It's not the years, it's the mileage.
858−It's only a game!
859−It's simple, clean, it works, and you can get it right now. -Mike O'Dell
860−It's some kind of instinct...This was an important place in their lives.
861−It's the law: Use a pun, go to prism (for minor refractions of the law only!)
862−It's the thought, if any, that counts! -Dick Grantges
863−It's time to gearshift up from the crawl we've been in to a full trot. - Jack Scanlon
864−It's worse than being at the theatre.
865−Jam tomorrow and jam yesterday -- but never jam today.
866−Jesus Rodrigues has a 9-inch duck.
867−Jesus saves, Moses invests, the Mongol Hoards, but only Buddha pays dividends.
868−Join me and I will complete your training.
869−Journalism will kill you, but it will keep you alive while you're at it.
870−Just be glad you don't get all the government you pay for. -Will Rogers
871−Just because you're paranoid doesn't mean they're not out to get you.
872−Justice for the poor is much less popular than revenge on the rich.
873−Keep emotionally active. Cater to your favorite neurosis.
874−Ken Thompson can't beat Belle. So what? How fast can Seymour Cray add?
875−Kids are always the only future the human race has. -William Saroyan
876−Kill ugly radio!
877−Klaatu barada nikto.
878−Kleeneliness is next to Goedeliness.
879−Label on a bottle of pills: "Do not take these pills if this label is missing"
880−Lack of leadership is no substitute for inaction.
881−Lando's not a system, he's a man. He's a gambler, scoundrel. You'd like him.
882−Language is a virus from outer space. -William Burroughs.
883−Language is all that separates us from the lower animals and the bureaucrats.
884−Last login: Sat Aug 10 09:22:14 on ttym0
885−Laugh and the world laughs with you; snore and you sleep alone.
886−Laugh, and the world ignores you. Crying doesn't help either.
887−Lay on, MacDuff, and curs'd be him who first cries, `Hold, enough!'
888−Leadership means taxes.
889−Lest men suspect your tale untrue,/Keep probability in view. -John Gay (1727)
890−Let a fool hold his tongue and he will pass for a sage.
891−Let him who takes the Plunge remember to return it by Tuesday.
892−Let no one unskilled in geometry enter here. -Plato
893−Let not the sands of time get in your lunch.
894−Let sleeping wraiths lie.
895−Let's just take this shortcut across this field. That bull doesn't see us.
896−Let's look at the record. -Al Smith
897−Li'l dollink, always fetful.
898−Liar: One who tells an unpleasant truth.
899−Life is a game: whoever dies with the most toys wins.
900−Life is a giant shell and we're just processes.
901−Life is a mystery -- love is a dancer.
902−Life is a yo-yo, and mankind ties knots in the string.
903−Life is hard but unjust.
904−Life is just a bowl.
905−Life is not for everyone. -M. O'Donoghue
906−Life is what happens to you while you're busy making other plans.
907−Like winter snow on summer lawn, time past is time gone.
908−Little girls have pretty curls, but I like Oreos.
909−Little things come in small packages.
910−Live forever, or die trying.
911−Live long and perspire.
912−Living in the past has one thing in its favour - it's cheaper.
913−Load average too high now (11.358253), please try later
914−Local disks are our FORTRAN. -Warren Teitelman
915−Long computations which yield 0 (zero) are probably all for naught.
916−Longevity is an optimist's heaven and a pessimist's hell.
917−Look after the molehills and the mountains will look after themselves.
918−Look on my works, oh ye mighty, and giggle.
919−Lord? We don't have no lord. We're an anarcho-syndicalist commune.
920−Lose a few, lose a few.
921−Losing your servo track is just God's way of saying `BOOGA, BOOGA!'
922−Love and scandal are the best sweeteners of tea.
923−Love is a many gendered thing.
924−Love is in the offing, said the homicidal maniac.
925−Love is only love, but money is forever.
926−Love the sea? I dote upon it - from the beach.
927−Love, and do what thou wilt.
928−Luchamos contra el Wombat, otra enemigo de la humanidad. -Frente Wombato de Liberacion Nacional
929−Luke, don't give in to hate. That leads to the dark side.
930−MOUNT TAPE U1439 ON B3, NO RING
931−Machne oprating at olny tn prcnt eficiency.
932−Macro context switch under way, please do not log out!
933−Make War, not Love: killing is fun too. -Nicholas von Hoffman
934−Make a list of all the facts you know about the universe.
935−Make is like Pascal: everybody likes it, so they go in and change it. -DM Ritchie
936−Make use of whatever advanced technology is available
937−Make: Don't know how to make love. Stop.
938−Making outside money using our computers has resulted in suspension.
939−Making sense makes more sense than not making sense. -T. Duff
940−Male tyrannosaurs may have used their diminutive front legs to titillate female partners, but this will not explain why they got so small. - Gould and Lewontin
941−Man cannot live by bread alone: frequently, there must be beverage, too.
942−Man cannot live by bread alone; he needs a little peanut butter on it.
943−Man has created death. -William Butler Yeats
944−Man is in doubt to deem himself a god or beast. -Alexander Pope
945−Man is in session.
946−Man who falls in vat of molten optical glass makes spectacle of self.
947−Man's horizons are bounded by his vision.
948−Many are called, few are chosen. Fewer still get to do the choosing.
949−Many are called, few volunteer.
950−Many are cold, but few are frozen.
951−Many pages make a thick book.
952−Marriage is a ghastly public confession of a strictly private intention.
953−Marriage is an attempt to change a night owl into a homing pigeon.
954−Masterpieces make their own rules.
955−May I have a large container of coffee?
956−May the bluebird of happiness twiddle your bits.
957−May you live all the days of your life.
958−May your rolling stone always grow grass that is greener underneath.
959−Maybe I should have screwed up. - Ken Thompson
960−Mcc may be slow and generate bad code, but it took a long time to develop.
961−Medeis ageometretos eisito mou ten stegen. -Plato
962−Members of an avian species of identical plumage congregate.
963−Men seldom make passes at girls who wear glasses. -Dorothy Parker.
964−Men seldom show dimples to girls who have pimples.
965−Message will arrive in the mail. Destroy, before the FBI sees it.
966−Micronics makes it simple.
967−Might as well be frank, monsieur. It would take a miracle to get you out of Casablanca.
968−Military justice is to justice as military music is to music. -Clemenceau
969−Military music is to music as military intelligence is to intelligence
970−Mind your own business, Spock. I'm sick of your halfbreed interference.
971−Misery loves company, but company does not reciprocate.
972−Misfortunes arrive on wings and leave on foot.
973−Mistakes are oft the stepping stones to failure.
974−Money cannot buy happiness, but happiness will not buy groceries.
975−Money is a terrible thing to follow but a charming thing to meet.
976−Money is the root of all evil, and man needs roots.
977−Money may buy friendship but money can not buy love.
978−Money will say more in one moment than the most eloquent lover can in years.
979−Most sacrilegious murder hath broke ope/The Lord's anointed temple. -MacBeth
980−Most users are within a 10 mile radius.
981−Mr. President! We cannot allow ... a MINE-SHAFT GAP!
982−Multi sunt vocati, pauci vero electi.
983−Multilevel standards are like onions. They're smelly and make you cry a lot. -Ron Natalie
984−My broker is E. F. Hutton, and E. F. Hutton says...
985−My karma just ran over your dogma.
986−My program is so jammed with clever tricks - GJ Holzmann
987−My way of joking is to tell the truth; it's the funniest joke in the world.
988−NOT NOT NOT ALLOWED
989−Naked is the best disguise.
990−National security is the chief cause of national insecurity.
991−Need a personal problem? Get a personal computer. - C. P. Killian
992−Neither a borrower nor a lender be/For loan oft loses both itself and friend.
993−Nembutal numbs it all, but I prefer alcohol. -Strummer/Jones
994−Netnews is someone yelling "Anybody wanna buy a used car?" in a crowded theater.
995−Never argue with a fool -- people might not know the difference.
996−Never attribute to malice what can be found in scientific american, under computer recreations.
997−Never buy a case of wine with eleven bottles.
998−Never call a man a fool. Borrow from him.
999−Never eat anything bigger than your head.
1000−Never eat in a restaurant that rotates or is above the 10th floor.
1001−Never eat rutabaga on any day of the week that has a "y" in it.
1002−Never give a inch!
1003−Never hatchet your Counts before they chicken.
1004−Never lick a gift horse in the mouth.
1005−Never put off till tomorrow what you can avoid altogether.
1006−Never speak ill of yourself; your friends will always say enough on that subject.
1007−Never stow away on a kamikaze plane.
1008−Never worry the boss unnecessarily. Don't tell him.
1009−New career ideas are worth pursuing.
1010−New crypt. See /usr/news/crypt.
1011−Niagara Falls is the second-biggest disappointment in a bride's life. -O. Wilde
1012−Niagara Falls is the wise bird who builds her nest in a chinese computer terminal!
1013−Niagara Falls would be much more impressive if it flowed the other way. - Oscar Wilde
1014−Nihilism means nothing to the dancing peasants.
1015−Nihilism should commence with oneself.
1016−No amount of genius can overcome a preoccupation with detail.
1017−No branch is better than its trunk.
1018−No directory
1019−No directory! Logging in with home=/
1020−No good deed goes unpunished. -Clare Booth Luce.
1021−No jaggies!
1022−No man's life, liberty or property are safe while the legislature is in session.
1023−No mistake is too small to be fixed, but first make sure it's a mistake.
1024−No news is good news.
1025−No note is too high to be taken down an octave.
1026−No one can feel as helpless as the owner of a sick goldfish.
1027−No two ways about it, there are two sides to every story.
1028−No user jobs will be lost because of the crash.
1029−Nobody can be as agreeable as an uninvited guest.
1030−Nobody expects the Spanish Inquisition!
1031−Nobody goes to the theatre unless suffering from acute bronchitis.
1032−Nobody is truly sane until he feels gratitude to the whole universe.
1033−Nobody knows anything, or if they do, they are careful to hide the fact.
1034−Nobody takes computer graphics seriously, even the guys that do it. -T. Duff
1035−Non serviam.
1036−Nostalgia isn't what it used to be.
1037−Not all the water in a rough rude sea/Can wash the balm from an anointed king.
1038−Not only is there no God, but try getting a plumber on Sundays.
1039−Nothing astonishes men so much as common sense and plain dealing.
1040−Nothing difficult is ever easy. -Steve Falco
1041−Nothing is as easy as it looks.
1042−Nothing is capable of being well set to music that is not nonsense. - Joseph Addison.
1043−Nothing is impossible for the man who doesn't have to do it himself.
1044−Nothing is impossible for the man who will not listen to reason.
1045−Nothing is true. Everything is permissible. -Hassan i Sabbah
1046−Nothing matters indeed, it's all in your mind...
1047−Nothing more certain than incertainties; Fortune is full of fresh variety: Constant in nothing but inconstancy. - Richard Barnfield.
1048−Nothing of interest ever happened on this day.
1049−Nothing works. No one knows why. And some jerk is talking French. -Bob Lied
1050−Now and then an innocent man is sent to the legislature.
1051−Now is the winter of our discontent, made glorious summer in Northern California.
1052−Now is the winter of our discontent/Made glorious summer by this sun of York.
1053−O brave new world,/That has such people in't!
1054−O dear Ophelia! I am ill at these numbers: I have not art to reckon my groans.
1055−O.T.O. wants you.
1056−OK, I think I understand.
1057−OS 360 -- Not uranium.
1058−Of all forms of caution, caution in love is the most fatal.
1059−Of all things man is the measure. -Protagoras
1060−Oh, don't the days seem lank and long, when all goes right and nothing goes wrong.
1061−Oh, so there you are!
1062−Old MacDonald had an agricultural real estate tax abatement.
1063−Old age -- it's the only disease that you don't look forward to being cured of.
1064−Omnibus ex nihil ducendis sufficit unum. -Gottfried Wilhelm von Leibniz
1065−On a clear disk you can seek forever.
1066−Once TOAD is operational, how frequently would you expect to access TOAD?
1067−One Bell System -- it sometimes works.
1068−One Bell System -- it works.
1069−One bad apple can ruin a snake.
1070−One horse-laugh is worth ten thousand syllogisms. -H. L. Mencken
1071−One man tells a falsehood, a hundred repeat it as true.
1072−One man's Mede is another man's Persian.
1073−One picture is worth 128k words.
1074−One scythe fits all.
1075−One starts life with a swelled head and ends with swelled feet. -Ezra Pound
1076−Only %d shopping days until Christmas.
1077−Only God can make a random selection.
1078−Only someone with nothing to be sorry for smiles back at the rear of an elephant.
1079−Only two things are infinite: the universe and human ignorance. -A. Einstein
1080−Ontogeny recapitulates phylogeny, or is that ontology recapitulates philology?
1081−Ontogeny recapitulates phylogeny. -Haeckel
1082−Ontogeny rehashes phylogeny.
1083−Ooh, Andy Tannenbaum? His netnews is SO derivative.
1084−Options can cause undesirable operations, so it is important to ensure they are set up properly.
1085−Order ignorant aliens.
1086−Others will look to you for stability, so hide when you bite your nails.
1087−Otto's too so-so to toss soot, too sot to toot SOSs. So?
1088−Our ancestors may have been ignorant, but they were not stupid.
1089−Our sponsor thought it was for ADA. In fact it was for C.
1090−Our vision will speed up time, eventually deleting it. -Alexander Schure
1091−Out of memory saving lines for undo - try using ed.
1092−Out of the mouths of babes comes semi-digested Pablum.
1093−Overall there is a smell of fried onions. (fnord)
1094−Pack my box with five dozen liquor jugs.
1095−Panem et circenses, that's what the public wants.
1096−Paranoia doesn't mean the whole world really isn't out to get you.
1097−Pardon me for breathing, which I never do anyway oh, God, I'm so depressed...
1098−Passing over a black hole temporarily disables ship.
1099−Password:
1100−People get it into their heads that this is a democracy. Well it isn't. -gwl
1101−People never go there anymore; it's too crowded. -Yogi Berra
1102−People really shouldn't spread gossip, but what else is it good for?
1103−People tend to congregate in the back of the church and the front of the bus.
1104−People usually do what other people have done before them.
1105−People who deal with bits should expect to get bitten. -Jon Bentley
1106−People who take cat naps don't usually sleep in a cat's cradle.
1107−People who think they know everything greatly annoy us who do.
1108−People will buy anything that's one to a customer.
1109−Per omnia saecula vombatidae.
1110−Perfect day for scrubbing the floor and other exciting things.
1111−Perfect love casteth out fear.
1112−Person who falls in blast furnace is certain to feel overwrought.
1113−Personality is a flimsy thing on which to build an art. -John Cage
1114−Philosophy is the Rule of Life.
1115−Philosopy: unintelligible answers to insoluble problems.
1116−Physician, bill thyself.
1117−Planning dooms most projects.
1118−Please log off, the computer is out to get in your room and drink?
1119−Please log off, the computer is out to lunch.
1120−Please take note:
1121−Please to remember the Fifth of November, Gunpowder Treason and Plot.
1122−Plunk your magic twanger, froggy.
1123−Pluralites non est punenda sine necessitate. -Wm. of Occam
1124−Plus ça change, plus c'est la même chose.
1125−Politicians, ugly buildings and whores all get respectable if they last long enough.
1126−Populus vult decipi.
1127−Pornography is in the groin of the beholder. -William F. Buckley
1128−Post hoc, ergo propter hoc.
1129−Post proelium, praemium.
1130−Pregnant ropuli.
1131−Premature optimization is the root of all evil. -D. E. Knuth
1132−Preserve wildlife -- pickle a squirrel today!
1133−Prevention makes the heart grow fonder.
1134−Primate behaviour only changes under the impact of new technology.
1135−Pro is to con as progress is to Congress.
1136−Procrastination is the art of keeping up with yesterday. -Don Marquis
1137−Programming and puddings demand consistency.
1138−Progress is made on alternate Fridays.
1139−Promptness is its own reward, if one lives by the clock instead of the sword.
1140−Proofreading is more effective after publication.
1141−Proper planning includes admitting that your plan may not work.
1142−Pulchritude possesses solely cutaneous profundity.
1143−Put not your trust in money, but your money in trust.
1144−Put your mouth where your mouth is.
1145−Quantity is no substitute for quality, but it's the only one we've got.
1146−Quantum mechanics do it with uncertainty.
1147−Questions are a burden for others; answers are a prison for oneself.
1148−Rain before sunset, dark by midnight.
1149−Rainy days and Mondays always get me down.
1150−Reach out and grep someone.
1151−Reading is thinking with someone else's head instead of one's own.
1152−Real programmers can't say `lint' without adding `hbaxcu' -Wm Leler
1153−Real programs don't eat cache.
1154−Reality is for those who can't handle drugs.
1155−Reality is good for you...in small doses.
1156−Reality is silly-putty. -Paul Krassner
1157−Reality seems harsher in the early morning.
1158−Reason establishes the foundation of faith. Faith compensates the error of reason.
1159−Reason is a universal instrument which can serve on any kind of occasion. -Descartes
1160−Reform always comes from below. No man with four aces asks for a new deal.
1161−Regnant populi.
1162−Rei panta.
1163−Religions revolve madly around sexual questions.
1164−Remember that "almost" means "not".
1165−Remember the Unknown Buffalo.
1166−Remember when you asked me to tell you when you were being inconsiderate?
1167−Remember why the good Lord made your eyes -- Pla-gi-a-rize! -Tom Lehrer
1168−Remember, UNIX spelled backwards is XINU.
1169−Remember, even if you win the rat race -- you're still a rat.
1170−Render unto Caesar if line 54 is larger than line 62.
1171−Repetition is a form of change. -B. Eno
1172−Research is a great career: you get paid for looking, regardless of results.
1173−Respect you in the morning?! Hell, I don't even respect you now.
1174−Restrain your octopus! The canoes are going fishing tomorrow.
1175−Ring around the collar.
1176−Ring the bell; close the book; quench the candle.
1177−Ritual is to the inner sciences what experiment is to the outer sciences. -Leary
1178−Rog-O-Matic callidus est.
1179−Rog-O-Matic perditus est.
1180−Rog-O-Matic's not expert enough. It could handle rogue, but it couldn't handle More.
1181−Rotten wood can not be carved -Confucius (Analects, Book 5, Ch. 9)
1182−Round numbers are always false. -Samuel Johnson (c. 1750)
1183−Rule 5 Violation
1184−SCCS: the source-code motel -- your code checks in but it never checks out. Ken Thompson
1185−SYS ERROR 0 - no error detected
1186−Sailors in ships, sail on! Even while we died, others rode out the storm.
1187−Satire does not look pretty upon a tombstone.
1188−Save a forest -- eat a beaver!
1189−Save the dot files!
1190−Save yourself! Reboot in 5 seconds!
1191−Say "no" to long-sleeved shirts!! Support your right to bare arms!
1192−Say your prayers, you're going to Zen heaven.
1193−Schroedinger might have been here.
1194−Schroedinger's cat is sitting on Heisenberg's shoulder and they are both laughing at you.
1195−Scintillate, scintillate, aster minific.
1196−Screw up your courage! You've screwed up everything else.
1197−Secrecy is the beginning of tyranny.
1198−Secret mail has arrived.
1199−See that ocean -- that used to be some ocean. -Burt Lancaster in Atlantic City
1200−Seek not to understand that you may believe, but believe that you may understand.
1201−Self denial is better than self degradation.
1202−Sell everything. Market top has been reached. -Joseph Granville
1203−Send not to ask for whom the bell tolls; it tolls for thee.
1204−Señor, if you hurry from here, you will wait longer there. -Mexico taxi driver
1205−Sex with someone you don't love is just gymnastics--and I hate exercise. -John Derek
1206−Shadows slick as eels slither through.
1207−Share your happiness with others today.
1208−She canna take much more o' this, Mr. Spock.
1209−Shift to the left! Shift to the right! Pop up! Push Down! Byte, byte, byte!
1210−Show respect for age. Drink good Scotch for a change.
1211−Si nummi immunis.
1212−Silver is pure. It's been a symbol of justice and purity since the year of the sun.
1213−Sin has many tools, but a lie is the handle which fits them all.
1214−Sink or Swim with Teddy!
1215−Sleep is an excellent way of listening to an opera.
1216−Smile ... tomorrow will be worse.
1217−Smoked carp is terrible unless you're out of smoked salmon.
1218−Smooth rotation butters no parsnips. -J. W. Tukey
1219−Snatch the pebble from my hand, Grasshopper.
1220−Snob intellectual bachelors can't have fun in San Antonio. -Ted Nelson
1221−Snoopy has fleas.
1222−Snow Day -- stay home.
1223−So long as radicals honor theory over facts, they will continue to dismantle their successes.
1224−So narrow minded is the boss that he has to stack his ideas vertically.
1225−Social innovations tend to the level of minimum tolerable well being.
1226−Soft soap often has a high percentage of lye in it. -- Salada Tea
1227−Solve et coagule.
1228−Some books are to be tasted, others to be swallowed. -- Francis Bacon
1229−Some day this war's gonna end.
1230−Some men are discovered; others are found out.
1231−Some of us feel that there is a loss of scholarship here, and we're not too happy about it. -Irvin Lustig
1232−Some scholars are like donkeys, they merely carry a lot of books.
1233−Some things are better left unsaid.
1234−Sometimes a cigar is just a cigar. -Sigmund Freud
1235−Sometimes it seems to me that men are children grown incompetent. -Carl Whitaker
1236−Sometimes you've gotta give it all you've got, because it just isn't enough.
1237−Soon you will be sitting on top of the world.
1238−Sooner or later everybody's gotta pay their tab.
1239−Sorting on the part of mendicants must be interdicted.
1240−Space travel is utter bilge. -Sir Richard Van Der Riet Wolley
1241−Spare no expense to save money on this one. -Samuel Goldwyn
1242−Speaking of poison, I'll see that you get some fresh breakfast immediately.
1243−Specialization is for insects. -Robt. A. Heinlein
1244−Spend extra time on hobby. Get plenty of rolling papers.
1245−Split a stick of wood, and the Christ is there, too.
1246−Spock: We suffered 23 casualties in that attack, Captain.
1247−Stack overflow in crawlout. User environment re-initialized. (FATAL$)
1248−Standing on head makes smile of frown, but rest of face also upside down.
1249−Status: R
1250−Stay away from flying saucers today.
1251−Stay away from hurricanes for a while.
1252−Stereotypes are one of the worst things in the world. -miteddie!nessus
1253−Sticks and stones may break my bones, but a laser beam is another matter.
1254−Stop searching forever. Happiness is just next to you.
1255−Stop searching forever. Happiness is unattainable.
1256−Stop searching. Happiness is right next to you.
1257−Stop worrying, you'll never get out of this world alive.
1258−Subject: Re: Re: Clar ... HUMBUG! - Wrongthink st - (nf)
1259−Succumb to natural tendencies. Be hateful and boring.
1260−Sum quod eris.
1261−Sun UNIX 4.2 Release 1.1 (IAS) #1: Tue Jan 29 01:25:15 PST 1985
1262−Sunday clears away the rust of the whole week. - Joseph Addison.
1263−Sure [Somoza]'s a son-of-a-bitch, but he's OUR son-of-a-bitch. -F.D. Roosevelt
1264−Surprise due today. Also the rent.
1265−Surprise your boss. Get to work on time.
1266−Surveillance should precede salientation.
1267−System down Tues. am for COBOL compiler installation.
1268−System going down at 1:45 this afternoon for disk crash.
1269−System going down for 5 minutes -- back up in barrels.
1270−System going down for 5 minutes -- back up in half an hour.
1271−System going down in 5 minutes.
1272−System might crash at any moment.
1273−System went down at Fri Dec 13 21:54:56 1901
1274−TERROR IN THE OUTPUT FILE A A
1275−TNT allows students the freedom to make mistakes.
1276−TSO -- it may be slow, but it's hard to use.
1277−Tai Chi is self-defense for people on Quaaludes.
1278−Take care of the luxuries and the necessities will take care of themselves.
1279−Take care of your peonies and the dahlias will take care of themselves.
1280−Te ayudare a recorder la cantidad a indoctos si releesme bien.
1281−Teach it ... phenomenology.
1282−Technological unemployment is total today -- 300 years ago we were all farmers.
1283−Tell the girls to slice the ham thin.
1284−Ten years of rejection slips is nature's way of telling you to stop writing.
1285−Terminals at home are always in the bedroom.
1286−Thank God I'm an atheist. -Aleister Crowley
1287−Thank you for choosing UNIX -- batteries not included, some assembly required.
1288−That goes against the laws of Physics.
1289−That must be wonderful! I don't understand it at all.
1290−That we can comprehend the little we know already is mindboggling in itself.
1291−That which does not kill me makes me stronger.
1292−That which does not kill me missed.
1293−That which is above is in that which is below.
1294−That's as American as pie charts.
1295−That's the nice thing about standards -- there's so many to choose from. -trb
1296−The $SIGNON command is a risky practice.
1297−The 3B2 Model 100 - the first machine with cat -v in ROM!
1298−The Angels want to wear my red shoes.
1299−The Beatles? Isn't that Paul McCartney's old band?
1300−The Blit is a nice terminal, but it runs emacs.
1301−The Constitution gives us freedom of religion, not freedom from religion -R Reagan
1302−The Emperor is not as forgiving as I am.
1303−The Force is strong with this one.
1304−The Force is with you, young Skywalker, but you are not a Jedi yet.
1305−The Government urges you to remain calm.
1306−The Inuit have dozens of words for snow, so why do the Dutch only have one word for rain?
1307−The Italians make money out of funding their own deficit.
1308−The Luddites always lose. Always.
1309−The Moral Majority are the people our ancestors came from Europe to escape.
1310−The PIXAR -- it's not just a job, it's an adventure.
1311−The SUN really is a hunk of junk. - Tom Duff
1312−The Tao which can be talked about is not the Tao. -Lao Tzu
1313−The Tree of Learning bears the noblest fruit, but noble fruit tastes bad.
1314−The UFO and the BVM seem to be the same phenomenon. -Jacques Vallee
1315−The UNIX system is harder to use than a toaster. -Kaare Christian
1316−The United States Army: 194 years of proud service, unhampered by progress.
1317−The aim of existence is to have clean ideas, change them like shirts.
1318−The aim of existence is to offer resistance to the flow of time.
1319−The answer you seek is in an envelope.
1320−The attacker must vanquish; the defender need only survive.
1321−The average legislator is somewhere nearly all the time. -Herb Nore
1322−The barge was in my blind spot. - Peter Hobson, Cambridge cox
1323−The best prophet of the future is the past.
1324−The better part of valour is discretion; in the which better part I have saved my life.
1325−The boundary condition of the universe is that it has no boundary. - S. Hawking
1326−The check is in the mail.
1327−The churches must learn humility as well as teach it.
1328−The common Welsh name Bzjxxllwcp is pronounced Jackson.
1329−The connotation depends on the beacon. - Mark V. Shaney
1330−The contrary of a compound is the aggregate of the contraries of the components. - De Morgan
1331−The contrary of an aggregate is the compound of the contraries of the aggregates. - De Morgan
1332−The coroner gave you a clean bill of health.
1333−The darkest hour is just before the storm.
1334−The dawning of the Information Age is bringing about dramatic changes in the fundamental fabric of our civilization. - AA Penzias
1335−The decision doesn't have to be logical, it was unanimous.
1336−The difference between a thief and the IRS is that the thief doesn't audit you afterwards.
1337−The difficult we gave up on yesterday, the impossible we are giving up on now.
1338−The early bird gets the coffee left over from the night before.
1339−The early worm gets the bird.
1340−The earth is like a tiny grain of sand, only much, much heavier.
1341−The empty fist always makes the deepest wound.
1342−The end is closer than you think.
1343−The end justifies the meanness.
1344−The enemy is ignorance [our own]. -Ezra Pound
1345−The eyes believe themselves, the ears believe other people.
1346−The fear of the lord was discovered before vitamins.
1347−The first piece of luggage out of the chute doesn't belong to anyone, ever.
1348−The first step in fixing something is getting it to break.
1349−The first thing we do, let's kill all the lawyers. - Henry VI, part II.
1350−The fit between the world and the human symbols describing it is never perfect.
1351−The following file systems are due for backup at this time:
1352−The fruits of impatience are bitter.
1353−The function of the sun is not to help the cabbages along. - Flaubert
1354−The further you get, the better it looks.
1355−The future isn't what it used to be. (It never was.)
1356−The future isn't what it used to be. -Arthur C. Clarke
1357−The gods do not protect fools. Fools are protected by more capable fools.
1358−The hardest job kids face today is learning good manners without seeing any.
1359−The hardest part of raising children is teaching them to ride bicycles.
1360−The hippo has no sting, but the wise man would rather be sat upon by the bee.
1361−The human brain is not a pretty sight.
1362−The human mind treats a new idea the way the body treats a strange protein - it rejects it. -Peter Medawar
1363−The invention of the multiple-choice exam was the death blow to competent writing.
1364−The judge's jokes are always funny.
1365−The ketchup of sorrow is better than the mustard of happiness.
1366−The last twenty-nine days of the month are the worst. -Nicola Tesla
1367−The lion will lie down with the lamb, but the lamb won't get much sleep.
1368−The love of money is the mucilage of many a tragic friendship -Stuart McMillan
1369−The man of knowledge can see several things at once.
1370−The map is not the territory. -A. E. Van Vogt, in World of Null-A
1371−The measure of the rigor of a science is the index of its ability to predict.
1372−The meek shall inherit the earth -- they are careful to hide the fact.
1373−The meek shall inherit the earth -- they are pronounced "o".
1374−The meek shall inherit the earth -- they are too weak to refuse.
1375−The more complicated the mind, the more simple the play.
1376−The more things change, the more they'll never be the same again.
1377−The more you run over a dead cat, the flatter it gets.
1378−The move of bambam functionality to the new AP bugs is re-scheduled to Friday night
1379−The nervous system sees no color, feels no pain. -T. Leary
1380−The null string has always been a locksmith. -Albert Einstein
1381−The null string has always been a productive source of off-by-0 errors.
1382−The number of UNIX installations has grown to 10, with more expected. - 2nd Edition UNIX manual
1383−The number of approved [COBOL] subsets has been reduced from 104,976 to 54. - JM Triance
1384−The official state animal of New York is the cabbie.
1385−The official state tree of North Dakota is the telephone pole?
1386−The one interesting fact about the Diplodocus is that the accent is on the second syllable.
1387−The only imperfect thing in nature is the human race.
1388−The only one who got everything done by Friday was Robinson Crusoe.
1389−The only people who listen to both sides of an argument are the neighbors.
1390−The only sure things in life are net.suicide and net.taxes.
1391−The only thing cheaper than hardware is talk.
1392−The only way out of a circle is through the center.
1393−The opera isn't over until the fat lady sings.
1394−The opposite of a trivial truth is false; the opposite of a great truth is also true.
1395−The pale companion is not for our pomp.
1396−The pearl the squirrel the girl hit bit split.
1397−The planes in Spain fall mainly in the rain.
1398−The play's the thing/Wherein I'll catch the conscience of the king.
1399−The plural of spouse is spice.
1400−The polhode rolls without slipping on the herpolhode lying in the invariable plane.
1401−The problem with a just economy is, who runs the Bureau of Economic Justice?
1402−The prudent man does not hold his breath.
1403−The reason Swedes put little o's over some A's is that ontology recapitulates philology.
1404−The reason Swedes put little o's over some A's is that they are pronounced "o".
1405−The religion that is afraid of science dishonors God and commits suicide.
1406−The rich man has his motor car, His country and his town estate. He smokes a fifty-cent cigar And jeers at Fate. - F. P. Adams
1407−The screen rectangle must be charged with emotion. Hitchcock
1408−The sheep - symbolic creature of docility, sacrifice and stupidity.
1409−The shorter the line, the slower it moves.
1410−The shortest distance between two points is off the wall.
1411−The shortest distance between two points is under construction. -Noelie Altito
1412−The skeletons in the cupboard will all come out in the wash.
1413−The solution to the problem of life is seen in the vanishing of the problem.
1414−The sooner you fall behind, the more time you have to catch up.
1415−The stapler runs out of staples only while you are trying to staple something.
1416−The sterile pleasure of being right tends to get stale in the course of a lifetime. EW Dijkstra
1417−The strength of a nation lies in the integrity of its homes. -Confucius
1418−The stylus is more potent than the claymore.
1419−The sword he sang a song of death/But could not make the sickle yield. -Blake
1420−The thing about Chinatown is, you can never be sure of anything down there.
1421−The three laws of physics: f=ma; things fall down; you can't push a rope.
1422−The tide of change approaches.
1423−The time is right to make new friends.
1424−The unexamined life is not worth examining.
1425−The universe is laughing behind your back.
1426−The vanity of teaching often tempteth a man to forget that he is a blockhead.
1427−The voice of the people is odd,/It is, and it is not, the voice of God. -Pope
1428−The wheels of justice grind slow but fine.
1429−The whole UNIX operating system was ripped off electronically.
1430−The whole UNIX operating system whose documentation fits in a chinese computer terminal!
1431−The wise shepherdess never trusts her flock to a smiling wolf.
1432−The world cannot be understood from a single point of view. -Eleanor Roosevelt
1433−The world ended yesterday-this is only a dream!
1434−The world ended yesterday-why are you still here?
1435−The world is a conspiracy of the unthinking against the unwitting.
1436−The world is all that is the case. -Wittgenstein
1437−The world is coming to an end! Repent and return those library books!
1438−Them that dishes it out need not fall over every time someone blows hard.
1439−There are more old drunkards than old doctors.
1440−There are more things in heaven and earth, Horatio,/Than are dreamt of in your philosophy.
1441−There are more ways of killing a cat than choking her with cream.
1442−There are no color bars in Cuba.
1443−There are only three kinds of proof: induction, exhaustion, and intimidation.
1444−There are two kinds of people in the world -- those who are, and those who aren't.

3791 more lines aren’t shown here.

sys/games/lib/fortunes.index+0−0

Binary file not shown.

sys/games/lib/life/2.eaters+0−9

This diff is large: its 10 lines aren’t shown here.

sys/games/lib/life/34osc+0−47

This diff is large: its 48 lines aren’t shown here.

sys/games/lib/life/55555+0−1

This diff is large: its 2 lines aren’t shown here.

sys/games/lib/life/5row+0−1

This diff is large: its 2 lines aren’t shown here.

sys/games/lib/life/acorn+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/background1+0−59

This diff is large: its 60 lines aren’t shown here.

sys/games/lib/life/baker+0−95

This diff is large: its 96 lines aren’t shown here.

sys/games/lib/life/bakery+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/barber.pole+0−19

This diff is large: its 20 lines aren’t shown here.

sys/games/lib/life/barberpole+0−13

This diff is large: its 14 lines aren’t shown here.

sys/games/lib/life/beacon+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/beaconmaker+0−25

This diff is large: its 26 lines aren’t shown here.

sys/games/lib/life/benchmark+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/bheptomino+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/biclock+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/billiard.clock+0−12

This diff is large: its 13 lines aren’t shown here.

sys/games/lib/life/billiard1+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/billiard2+0−10

This diff is large: its 11 lines aren’t shown here.

sys/games/lib/life/billiard3+0−12

This diff is large: its 13 lines aren’t shown here.

sys/games/lib/life/billiard4+0−13

This diff is large: its 14 lines aren’t shown here.

sys/games/lib/life/billiard5+0−15

This diff is large: its 16 lines aren’t shown here.

sys/games/lib/life/billiard6+0−14

This diff is large: its 15 lines aren’t shown here.

sys/games/lib/life/billiardgeorge+0−19

This diff is large: its 20 lines aren’t shown here.

sys/games/lib/life/billiardsmall+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/biloaf+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/blanker+0−2

This diff is large: its 3 lines aren’t shown here.

sys/games/lib/life/blinker+0−1

This diff is large: its 2 lines aren’t shown here.

sys/games/lib/life/blinkership+0−17

This diff is large: its 18 lines aren’t shown here.

sys/games/lib/life/block+0−2

This diff is large: its 3 lines aren’t shown here.

sys/games/lib/life/boat.factory+0−98

This diff is large: its 99 lines aren’t shown here.

sys/games/lib/life/boatcap+0−14

This diff is large: its 15 lines aren’t shown here.

sys/games/lib/life/boatmaker+0−26

This diff is large: its 27 lines aren’t shown here.

sys/games/lib/life/breeder+0−338

This diff is large: its 339 lines aren’t shown here.

sys/games/lib/life/breeder4753+0−337

This diff is large: its 338 lines aren’t shown here.

sys/games/lib/life/c1+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/c2+0−11

This diff is large: its 12 lines aren’t shown here.

sys/games/lib/life/c3+0−17

This diff is large: its 18 lines aren’t shown here.

sys/games/lib/life/c4+0−23

This diff is large: its 24 lines aren’t shown here.

sys/games/lib/life/c5+0−29

This diff is large: its 30 lines aren’t shown here.

sys/games/lib/life/c6+0−35

This diff is large: its 36 lines aren’t shown here.

sys/games/lib/life/c7+0−41

This diff is large: its 42 lines aren’t shown here.

sys/games/lib/life/c8+0−47

This diff is large: its 48 lines aren’t shown here.

sys/games/lib/life/c9+0−53

This diff is large: its 54 lines aren’t shown here.

sys/games/lib/life/candelabra+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/capsule8+0−11

This diff is large: its 12 lines aren’t shown here.

sys/games/lib/life/catherinewheel+0−12

This diff is large: its 13 lines aren’t shown here.

sys/games/lib/life/cheshire.cat+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/cheshirecat+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/clappinghands+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/clean.fuse+0−159

This diff is large: its 160 lines aren’t shown here.

sys/games/lib/life/clock+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/clock2+0−12

This diff is large: its 13 lines aren’t shown here.

sys/games/lib/life/cmu+0−15

This diff is large: its 16 lines aren’t shown here.

sys/games/lib/life/cmu2+0−17

This diff is large: its 18 lines aren’t shown here.

sys/games/lib/life/cmu3+0−19

This diff is large: its 20 lines aren’t shown here.

sys/games/lib/life/collapsecap+0−14

This diff is large: its 15 lines aren’t shown here.

sys/games/lib/life/cow+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/cp.48-56-72+0−13

This diff is large: its 14 lines aren’t shown here.

sys/games/lib/life/crab+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/cross+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/diagfuse+0−16

This diff is large: its 17 lines aren’t shown here.

sys/games/lib/life/diamond+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/dirty.fuse+0−159

This diff is large: its 160 lines aren’t shown here.

sys/games/lib/life/eaters3+0−9

This diff is large: its 10 lines aren’t shown here.

sys/games/lib/life/eden+0−9

This diff is large: its 10 lines aren’t shown here.

sys/games/lib/life/figure8+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/fisheater+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/life/flare.path+0−97

This diff is large: its 98 lines aren’t shown here.

sys/games/lib/life/flasher+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/flip.flop+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/flotilla+0−52

This diff is large: its 53 lines aren’t shown here.

sys/games/lib/life/flywheel+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/fool+0−12

This diff is large: its 13 lines aren’t shown here.

sys/games/lib/life/fusebranch+0−26

This diff is large: its 27 lines aren’t shown here.

sys/games/lib/life/fusecorner+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/life/fusehinge+0−14

This diff is large: its 15 lines aren’t shown here.

sys/games/lib/life/futility+0−34

This diff is large: its 35 lines aren’t shown here.

sys/games/lib/life/fuzzcapsule+0−12

This diff is large: its 13 lines aren’t shown here.

sys/games/lib/life/gear+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/glider+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/glider.f+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/glider.gun+0−9

This diff is large: its 10 lines aren’t shown here.

sys/games/lib/life/glider.havoc+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/glider.step+0−9

This diff is large: its 10 lines aren’t shown here.

sys/games/lib/life/glider.thing1+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/glider.thing2+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/gliderarmyof25+0−78

This diff is large: its 79 lines aren’t shown here.

sys/games/lib/life/glidercap1+0−14

This diff is large: its 15 lines aren’t shown here.

sys/games/lib/life/glidercap2+0−14

This diff is large: its 15 lines aren’t shown here.

sys/games/lib/life/glidercap3+0−20

This diff is large: its 21 lines aren’t shown here.

sys/games/lib/life/glidercap4+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/life/glidercap5+0−17

This diff is large: its 18 lines aren’t shown here.

sys/games/lib/life/gliderglidergu+0−25

This diff is large: its 26 lines aren’t shown here.

sys/games/lib/life/glidergun+0−12

This diff is large: its 13 lines aren’t shown here.

sys/games/lib/life/glidergun2+0−34

This diff is large: its 35 lines aren’t shown here.

sys/games/lib/life/gliders.12+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/gliders.hex+0−9

This diff is large: its 10 lines aren’t shown here.

sys/games/lib/life/gosper.flop+0−72

This diff is large: its 73 lines aren’t shown here.

sys/games/lib/life/greymatter1+0−26

This diff is large: its 27 lines aren’t shown here.

sys/games/lib/life/gun.builder+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/gun.gliders+0−21

This diff is large: its 22 lines aren’t shown here.

sys/games/lib/life/gunandeater+0−21

This diff is large: its 22 lines aren’t shown here.

sys/games/lib/life/h.heptomino+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/harvester+0−96

This diff is large: its 97 lines aren’t shown here.

sys/games/lib/life/heavy.ship+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/hepto.shuttle+0−11

This diff is large: its 12 lines aren’t shown here.

sys/games/lib/life/hertz.osc+0−17

This diff is large: its 18 lines aren’t shown here.

sys/games/lib/life/horizfuse+0−2

This diff is large: its 3 lines aren’t shown here.

sys/games/lib/life/j+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/kickback+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/lambdabomb+0−2

This diff is large: its 3 lines aren’t shown here.

sys/games/lib/life/largefish+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/light.ship+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/longfuse+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/longfuse2+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/mathematician+0−12

This diff is large: its 13 lines aren’t shown here.

sys/games/lib/life/mediumfish+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/mediumfishgun+0−91

This diff is large: its 92 lines aren’t shown here.

sys/games/lib/life/methuselah+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/middle.ship+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/mip+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/morejunk+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/new.gun+0−34

This diff is large: its 35 lines aren’t shown here.

sys/games/lib/life/osc26+0−39

This diff is large: its 40 lines aren’t shown here.

sys/games/lib/life/osc28+0−14

This diff is large: its 15 lines aren’t shown here.

sys/games/lib/life/osc55+0−27

This diff is large: its 28 lines aren’t shown here.

sys/games/lib/life/osc66+0−32

This diff is large: its 33 lines aren’t shown here.

sys/games/lib/life/osc72+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/oscillator1+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/oscillator2+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/oscillator3+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/overw8.ship+0−16

This diff is large: its 17 lines aren’t shown here.

sys/games/lib/life/penta.bounce+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/penta.death+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/penta.kill+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/penta.shuttle+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/pentadecathlon+0−1

This diff is large: its 2 lines aren’t shown here.

sys/games/lib/life/pi.heptomino+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/piecollection+0−10

This diff is large: its 11 lines aren’t shown here.

sys/games/lib/life/pifuse+0−56

This diff is large: its 57 lines aren’t shown here.

sys/games/lib/life/piston+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/piston2+0−11

This diff is large: its 12 lines aren’t shown here.

sys/games/lib/life/pjw+0−48

This diff is large: its 49 lines aren’t shown here.

sys/games/lib/life/puffer.train+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/life/pulsar-48-56-7+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/pulse1+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/pulse2+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/pump+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/queen.bee+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/r+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/r.pentomino+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/rake+0−19

This diff is large: its 20 lines aren’t shown here.

sys/games/lib/life/rake2+0−33

This diff is large: its 34 lines aren’t shown here.

sys/games/lib/life/relay+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/round+0−70

This diff is large: its 71 lines aren’t shown here.

sys/games/lib/life/rpentomino+0−3

This diff is large: its 4 lines aren’t shown here.

sys/games/lib/life/s.glider+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/saint+0−63

This diff is large: its 64 lines aren’t shown here.

sys/games/lib/life/shiningflower+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/ships.appear+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/ships.gliders+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/ships.vanish+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/shuttle+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/sixgliders+0−8

This diff is large: its 9 lines aren’t shown here.

sys/games/lib/life/skyline+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/smallfish+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/somejunk+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/spark+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/spark2+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/sparkfuse+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/sparktopifuse+0−25

This diff is large: its 26 lines aren’t shown here.

sys/games/lib/life/sq.11+0−13

This diff is large: its 14 lines aren’t shown here.

sys/games/lib/life/sq.9+0−11

This diff is large: its 12 lines aren’t shown here.

sys/games/lib/life/squareblinker+0−4

This diff is large: its 5 lines aren’t shown here.

sys/games/lib/life/squarecap+0−14

This diff is large: its 15 lines aren’t shown here.

sys/games/lib/life/squaredance+0−7

This diff is large: its 8 lines aren’t shown here.

sys/games/lib/life/stargaterepeat+0−13

This diff is large: its 14 lines aren’t shown here.

sys/games/lib/life/still+0−30

This diff is large: its 31 lines aren’t shown here.

sys/games/lib/life/still.lives+0−27

This diff is large: its 28 lines aren’t shown here.

sys/games/lib/life/swastika+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/switch.block+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/switch.engine+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/testtube+0−19

This diff is large: its 20 lines aren’t shown here.

sys/games/lib/life/thunderbird+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/thunderbirdfus+0−21

This diff is large: its 22 lines aren’t shown here.

sys/games/lib/life/time.bomb+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/toad+0−2

This diff is large: its 3 lines aren’t shown here.

sys/games/lib/life/tumblers+0−6

This diff is large: its 7 lines aren’t shown here.

sys/games/lib/life/turbine8+0−9

This diff is large: its 10 lines aren’t shown here.

sys/games/lib/life/virus.dies+0−29

This diff is large: its 30 lines aren’t shown here.

sys/games/lib/life/virus.lives+0−29

This diff is large: its 30 lines aren’t shown here.

sys/games/lib/life/washerwoman+0−5

This diff is large: its 6 lines aren’t shown here.

sys/games/lib/life/wave1+0−15

This diff is large: its 16 lines aren’t shown here.

sys/games/lib/life/weird.wheel+0−30

This diff is large: its 31 lines aren’t shown here.

sys/games/lib/mahjongg/backgrounds/default.bit+0−0

Binary file not shown.

sys/games/lib/mahjongg/images/border.bit+0−0

Binary file not shown.

sys/games/lib/mahjongg/images/gameover.bit+0−0

Binary file not shown.

sys/games/lib/mahjongg/images/mask.bit+0−0

Binary file not shown.

sys/games/lib/mahjongg/layouts/default.layout+0−81

This diff is large: its 82 lines aren’t shown here.

sys/games/lib/mahjongg/tilesets/default.tileset+0−0

Binary file not shown.

sys/games/lib/sokoban/images/cargo.bit+0−0

Binary file not shown.

sys/games/lib/sokoban/images/empty.bit+0−0

Binary file not shown.

sys/games/lib/sokoban/images/goal.bit+0−0

Binary file not shown.

sys/games/lib/sokoban/images/goalcargo.bit+0−0

Binary file not shown.

sys/games/lib/sokoban/images/left.bit+0−0

Binary file not shown.

sys/games/lib/sokoban/images/right.bit+0−0

Binary file not shown.

sys/games/lib/sokoban/images/wall.bit+0−0

Binary file not shown.

sys/games/lib/sokoban/images/win.bit+0−0

Binary file not shown.

sys/games/lib/sokoban/levels/easy.slc+0−1549

This diff is large: its 1550 lines aren’t shown here.

sys/games/lib/sokoban/levels/hard.slc+0−1521

This diff is large: its 1522 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-01-21.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-01-23.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-01-25.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-01-29.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-01-30.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-02.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-03.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-04.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-06.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-07.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-08.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-09.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-10.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-11.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-12.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-13.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-14.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-16.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-02-17.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-03.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-04.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-05.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-06.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-07.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-08.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-09.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-10.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-11.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-12.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-03-29.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-04-11.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-04-26.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-04-28.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy-2005-05-24.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy000.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy001.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/easy002.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-03-13.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-03-14.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-03-19.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-03-26.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-03-27.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-02.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-03.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-07.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-08.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-09.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-17.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-22.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-23.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-24.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-04-30.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-05-01.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-05-07.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-05-14.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-05-15.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-05-19.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-05-21.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-05-22.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard-2005-05-23.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/hard000.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-01-22.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-01-24.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-01-26.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-01-27.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-01-28.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-01-31.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-01.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-05.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-15.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-18.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-19.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-20.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-21.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-22.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-23.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-24.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-25.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-26.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-27.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-02-28.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-01.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-02.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-15.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-16.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-18.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-21.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-22.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-23.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-24.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-28.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-30.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-03-31.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-01.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-04.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-05.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-06.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-12.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-13.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-14.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-15.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-18.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-19.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-20.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-21.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-25.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-27.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-04-29.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-02.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-03.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-04.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-05.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-06.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-09.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-10.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-11.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-12.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-13.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-16.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-17.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-18.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-20.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-25.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-26.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium-2005-05-27.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium000.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium002.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/medium003.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/veasy000.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/veasy001.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/vhard-2005-03-17.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/vhard-2005-03-20.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/vhard-2005-03-25.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/vhard-2005-04-10.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/vhard-2005-04-16.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/boards/vhard-2005-05-08.su+0−18

This diff is large: its 19 lines aren’t shown here.

sys/games/lib/sudoku/images/1.bit+0−0

Binary file not shown.

sys/games/lib/sudoku/images/2.bit+0−0

Binary file not shown.

sys/games/lib/sudoku/images/3.bit+0−0

Binary file not shown.

sys/games/lib/sudoku/images/4.bit+0−0

Binary file not shown.

sys/games/lib/sudoku/images/5.bit+0−0

Binary file not shown.

sys/games/lib/sudoku/images/6.bit+0−0

Binary file not shown.

sys/games/lib/sudoku/images/7.bit+0−0

Binary file not shown.

sys/games/lib/sudoku/images/8.bit+0−0

Binary file not shown.

sys/games/lib/sudoku/images/9.bit+0−0

Binary file not shown.

sys/src/cmd/gs/386.h+10−1

This diff is large: its 22 lines aren’t shown here.

sys/src/games/4s.c+0−43

This diff is large: its 44 lines aren’t shown here.

sys/src/games/5s.c+0−99

This diff is large: its 100 lines aren’t shown here.

sys/src/games/ana.c+0−451

This diff is large: its 452 lines aren’t shown here.

sys/src/games/blabs/blabs.c+0−831

This diff is large: its 832 lines aren’t shown here.

sys/src/games/blabs/mkface+0−37

This diff is large: its 38 lines aren’t shown here.

sys/src/games/blabs/mkfile+0−31

This diff is large: its 32 lines aren’t shown here.

sys/src/games/c64/c64.c+0−382

This diff is large: its 383 lines aren’t shown here.

sys/src/games/c64/cpu.c+0−514

This diff is large: its 515 lines aren’t shown here.

sys/src/games/c64/dat.h+0−95

This diff is large: its 96 lines aren’t shown here.

sys/src/games/c64/fns.h+0−11

This diff is large: its 12 lines aren’t shown here.

sys/src/games/c64/mem.c+0−307

This diff is large: its 308 lines aren’t shown here.

sys/src/games/c64/mkfile+0−13

This diff is large: its 14 lines aren’t shown here.

sys/src/games/c64/vic.c+0−370

This diff is large: its 371 lines aren’t shown here.

sys/src/games/catback.p+0−481

This diff is large: its 482 lines aren’t shown here.

sys/src/games/catclock.c+0−387

This diff is large: its 388 lines aren’t shown here.

sys/src/games/doom/am_map.c+0−1345

This diff is large: its 1346 lines aren’t shown here.

sys/src/games/doom/am_map.h+0−52

This diff is large: its 53 lines aren’t shown here.

sys/src/games/doom/d_englsh.h+0−701

This diff is large: its 702 lines aren’t shown here.

sys/src/games/doom/d_event.h+0−123

This diff is large: its 124 lines aren’t shown here.

sys/src/games/doom/d_french.h+0−433

This diff is large: its 434 lines aren’t shown here.

sys/src/games/doom/d_items.c+0−138

This diff is large: its 139 lines aren’t shown here.

sys/src/games/doom/d_items.h+0−52

This diff is large: its 53 lines aren’t shown here.

sys/src/games/doom/d_main.c+0−1093

This diff is large: its 1094 lines aren’t shown here.

sys/src/games/doom/d_main.h+0−64

This diff is large: its 65 lines aren’t shown here.

sys/src/games/doom/d_net.c+0−760

This diff is large: its 761 lines aren’t shown here.

sys/src/games/doom/d_net.h+0−148

This diff is large: its 149 lines aren’t shown here.

sys/src/games/doom/d_player.h+0−213

This diff is large: its 214 lines aren’t shown here.

sys/src/games/doom/d_textur.h+0−51

This diff is large: its 52 lines aren’t shown here.

sys/src/games/doom/d_think.h+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/doom/d_ticcmd.h+0−55

This diff is large: its 56 lines aren’t shown here.

sys/src/games/doom/doomdata.h+0−223

This diff is large: its 224 lines aren’t shown here.

sys/src/games/doom/doomdef.c+0−38

This diff is large: its 39 lines aren’t shown here.

sys/src/games/doom/doomdef.h+0−322

This diff is large: its 323 lines aren’t shown here.

sys/src/games/doom/doomstat.c+0−39

This diff is large: its 40 lines aren’t shown here.

sys/src/games/doom/doomstat.h+0−296

This diff is large: its 297 lines aren’t shown here.

sys/src/games/doom/doomtype.h+0−66

This diff is large: its 67 lines aren’t shown here.

sys/src/games/doom/dstrings.c+0−72

This diff is large: its 73 lines aren’t shown here.

sys/src/games/doom/dstrings.h+0−66

This diff is large: its 67 lines aren’t shown here.

sys/src/games/doom/f_finale.c+0−738

This diff is large: its 739 lines aren’t shown here.

sys/src/games/doom/f_finale.h+0−53

This diff is large: its 54 lines aren’t shown here.

sys/src/games/doom/f_wipe.c+0−301

This diff is large: its 302 lines aren’t shown here.

sys/src/games/doom/f_wipe.h+0−71

This diff is large: its 72 lines aren’t shown here.

sys/src/games/doom/g_game.c+0−1676

This diff is large: its 1677 lines aren’t shown here.

sys/src/games/doom/g_game.h+0−79

This diff is large: its 80 lines aren’t shown here.

sys/src/games/doom/hu_lib.c+0−354

This diff is large: its 355 lines aren’t shown here.

sys/src/games/doom/hu_lib.h+0−196

This diff is large: its 197 lines aren’t shown here.

sys/src/games/doom/hu_stuff.c+0−638

This diff is large: its 639 lines aren’t shown here.

sys/src/games/doom/hu_stuff.h+0−66

This diff is large: its 67 lines aren’t shown here.

sys/src/games/doom/i_main.c+0−12

This diff is large: its 13 lines aren’t shown here.

sys/src/games/doom/i_net.c+0−161

This diff is large: its 162 lines aren’t shown here.

sys/src/games/doom/i_net.h+0−45

This diff is large: its 46 lines aren’t shown here.

sys/src/games/doom/i_sound.c+0−523

This diff is large: its 524 lines aren’t shown here.

sys/src/games/doom/i_sound.h+0−115

This diff is large: its 116 lines aren’t shown here.

sys/src/games/doom/i_system.c+0−144

This diff is large: its 145 lines aren’t shown here.

sys/src/games/doom/i_system.h+0−106

This diff is large: its 107 lines aren’t shown here.

sys/src/games/doom/i_video.c+0−372

This diff is large: its 373 lines aren’t shown here.

sys/src/games/doom/i_video.h+0−63

This diff is large: its 64 lines aren’t shown here.

sys/src/games/doom/info.c+0−4664

This diff is large: its 4665 lines aren’t shown here.

sys/src/games/doom/info.h+0−1339

This diff is large: its 1340 lines aren’t shown here.

sys/src/games/doom/m_argv.c+0−55

This diff is large: its 56 lines aren’t shown here.

sys/src/games/doom/m_argv.h+0−42

This diff is large: its 43 lines aren’t shown here.

sys/src/games/doom/m_bbox.c+0−60

This diff is large: its 61 lines aren’t shown here.

sys/src/games/doom/m_bbox.h+0−54

This diff is large: its 55 lines aren’t shown here.

sys/src/games/doom/m_cheat.c+0−101

This diff is large: its 102 lines aren’t shown here.

sys/src/games/doom/m_cheat.h+0−58

This diff is large: its 59 lines aren’t shown here.

sys/src/games/doom/m_fixed.c+0−64

This diff is large: its 65 lines aren’t shown here.

sys/src/games/doom/m_fixed.h+0−50

This diff is large: its 51 lines aren’t shown here.

sys/src/games/doom/m_menu.c+0−1878

This diff is large: its 1879 lines aren’t shown here.

sys/src/games/doom/m_menu.h+0−67

This diff is large: its 68 lines aren’t shown here.

sys/src/games/doom/m_misc.c+0−475

This diff is large: its 476 lines aren’t shown here.

sys/src/games/doom/m_misc.h+0−65

This diff is large: its 66 lines aren’t shown here.

sys/src/games/doom/m_random.c+0−82

This diff is large: its 83 lines aren’t shown here.

sys/src/games/doom/m_random.h+0−48

This diff is large: its 49 lines aren’t shown here.

sys/src/games/doom/m_swap.c+0−57

This diff is large: its 58 lines aren’t shown here.

sys/src/games/doom/m_swap.h+0−52

This diff is large: its 53 lines aren’t shown here.

sys/src/games/doom/mkfile+0−142

This diff is large: its 143 lines aren’t shown here.

sys/src/games/doom/p_ceilng.c+0−335

This diff is large: its 336 lines aren’t shown here.

sys/src/games/doom/p_doors.c+0−535

This diff is large: its 536 lines aren’t shown here.

sys/src/games/doom/p_enemy.c+0−2046

This diff is large: its 2047 lines aren’t shown here.

sys/src/games/doom/p_floor.c+0−547

This diff is large: its 548 lines aren’t shown here.

sys/src/games/doom/p_inter.c+0−918

This diff is large: its 919 lines aren’t shown here.

sys/src/games/doom/p_inter.h+0−41

This diff is large: its 42 lines aren’t shown here.

sys/src/games/doom/p_lights.c+0−361

This diff is large: its 362 lines aren’t shown here.

sys/src/games/doom/p_local.h+0−291

This diff is large: its 292 lines aren’t shown here.

sys/src/games/doom/p_map.c+0−1337

This diff is large: its 1338 lines aren’t shown here.

sys/src/games/doom/p_maputl.c+0−836

This diff is large: its 837 lines aren’t shown here.

sys/src/games/doom/p_mobj.c+0−990

This diff is large: its 991 lines aren’t shown here.

sys/src/games/doom/p_mobj.h+0−295

This diff is large: its 296 lines aren’t shown here.

sys/src/games/doom/p_plats.c+0−314

This diff is large: its 315 lines aren’t shown here.

sys/src/games/doom/p_pspr.c+0−864

This diff is large: its 865 lines aren’t shown here.

sys/src/games/doom/p_pspr.h+0−82

This diff is large: its 83 lines aren’t shown here.

sys/src/games/doom/p_saveg.c+0−584

This diff is large: its 585 lines aren’t shown here.

sys/src/games/doom/p_saveg.h+0−51

This diff is large: its 52 lines aren’t shown here.

sys/src/games/doom/p_setup.c+0−689

This diff is large: its 690 lines aren’t shown here.

sys/src/games/doom/p_setup.h+0−46

This diff is large: its 47 lines aren’t shown here.

sys/src/games/doom/p_sight.c+0−349

This diff is large: its 350 lines aren’t shown here.

sys/src/games/doom/p_spec.c+0−1354

This diff is large: its 1355 lines aren’t shown here.

sys/src/games/doom/p_spec.h+0−559

This diff is large: its 560 lines aren’t shown here.

sys/src/games/doom/p_switch.c+0−642

This diff is large: its 643 lines aren’t shown here.

sys/src/games/doom/p_telept.c+0−132

This diff is large: its 133 lines aren’t shown here.

sys/src/games/doom/p_tick.c+0−147

This diff is large: its 148 lines aren’t shown here.

sys/src/games/doom/p_tick.h+0−44

This diff is large: its 45 lines aren’t shown here.

sys/src/games/doom/p_user.c+0−386

This diff is large: its 387 lines aren’t shown here.

sys/src/games/doom/r_bsp.c+0−580

This diff is large: its 581 lines aren’t shown here.

sys/src/games/doom/r_bsp.h+0−72

This diff is large: its 73 lines aren’t shown here.

sys/src/games/doom/r_data.c+0−853

This diff is large: its 854 lines aren’t shown here.

sys/src/games/doom/r_data.h+0−62

This diff is large: its 63 lines aren’t shown here.

sys/src/games/doom/r_defs.h+0−490

This diff is large: its 491 lines aren’t shown here.

sys/src/games/doom/r_draw.c+0−743

This diff is large: its 744 lines aren’t shown here.

sys/src/games/doom/r_draw.h+0−115

This diff is large: its 116 lines aren’t shown here.

sys/src/games/doom/r_local.h+0−53

This diff is large: its 54 lines aren’t shown here.

sys/src/games/doom/r_main.c+0−806

This diff is large: its 807 lines aren’t shown here.

sys/src/games/doom/r_main.h+0−172

This diff is large: its 173 lines aren’t shown here.

sys/src/games/doom/r_plane.c+0−451

This diff is large: its 452 lines aren’t shown here.

sys/src/games/doom/r_plane.h+0−87

This diff is large: its 88 lines aren’t shown here.

sys/src/games/doom/r_segs.c+0−726

This diff is large: its 727 lines aren’t shown here.

sys/src/games/doom/r_segs.h+0−44

This diff is large: its 45 lines aren’t shown here.

sys/src/games/doom/r_sky.c+0−62

This diff is large: its 63 lines aren’t shown here.

sys/src/games/doom/r_sky.h+0−48

This diff is large: its 49 lines aren’t shown here.

sys/src/games/doom/r_state.h+0−138

This diff is large: its 139 lines aren’t shown here.

sys/src/games/doom/r_things.c+0−991

This diff is large: its 992 lines aren’t shown here.

sys/src/games/doom/r_things.h+0−72

This diff is large: its 73 lines aren’t shown here.

sys/src/games/doom/s_sound.c+0−804

This diff is large: its 805 lines aren’t shown here.

sys/src/games/doom/s_sound.h+0−109

This diff is large: its 110 lines aren’t shown here.

sys/src/games/doom/sounds.c+0−228

This diff is large: its 229 lines aren’t shown here.

sys/src/games/doom/sounds.h+0−289

This diff is large: its 290 lines aren’t shown here.

sys/src/games/doom/st_lib.c+0−293

This diff is large: its 294 lines aren’t shown here.

sys/src/games/doom/st_lib.h+0−226

This diff is large: its 227 lines aren’t shown here.

sys/src/games/doom/st_stuff.c+0−1468

This diff is large: its 1469 lines aren’t shown here.

sys/src/games/doom/st_stuff.h+0−86

This diff is large: its 87 lines aren’t shown here.

sys/src/games/doom/tables.c+0−2130

This diff is large: its 2131 lines aren’t shown here.

sys/src/games/doom/tables.h+0−92

This diff is large: its 93 lines aren’t shown here.

sys/src/games/doom/v_video.c+0−493

This diff is large: its 494 lines aren’t shown here.

sys/src/games/doom/v_video.h+0−119

This diff is large: its 120 lines aren’t shown here.

sys/src/games/doom/w_wad.c+0−576

This diff is large: its 577 lines aren’t shown here.

sys/src/games/doom/w_wad.h+0−78

This diff is large: its 79 lines aren’t shown here.

sys/src/games/doom/wi_stuff.c+0−1844

This diff is large: its 1845 lines aren’t shown here.

sys/src/games/doom/wi_stuff.h+0−54

This diff is large: its 55 lines aren’t shown here.

sys/src/games/doom/z_zone.c+0−466

This diff is large: its 467 lines aren’t shown here.

sys/src/games/doom/z_zone.h+0−86

This diff is large: its 87 lines aren’t shown here.

sys/src/games/eyes.p+0−20

This diff is large: its 21 lines aren’t shown here.

sys/src/games/festoon.c+0−1661

This diff is large: its 1662 lines aren’t shown here.

sys/src/games/gb/apu.c+0−484

This diff is large: its 485 lines aren’t shown here.

sys/src/games/gb/cpu.c+0−554

This diff is large: its 555 lines aren’t shown here.

sys/src/games/gb/dat.h+0−160

This diff is large: its 161 lines aren’t shown here.

sys/src/games/gb/ev.c+0−123

This diff is large: its 124 lines aren’t shown here.

sys/src/games/gb/fns.h+0−28

This diff is large: its 29 lines aren’t shown here.

sys/src/games/gb/gb.c+0−491

This diff is large: its 492 lines aren’t shown here.

sys/src/games/gb/mem.c+0−590

This diff is large: its 591 lines aren’t shown here.

sys/src/games/gb/mkfile+0−16

This diff is large: its 17 lines aren’t shown here.

sys/src/games/gb/ppu.c+0−341

This diff is large: its 342 lines aren’t shown here.

sys/src/games/gb/state.c+0−164

This diff is large: its 165 lines aren’t shown here.

sys/src/games/gba/apu.c+0−379

This diff is large: its 380 lines aren’t shown here.

sys/src/games/gba/cpu.c+0−1284

This diff is large: its 1285 lines aren’t shown here.

sys/src/games/gba/dat.h+0−156

This diff is large: its 157 lines aren’t shown here.

sys/src/games/gba/ev.c+0−226

This diff is large: its 227 lines aren’t shown here.

sys/src/games/gba/fns.h+0−28

This diff is large: its 29 lines aren’t shown here.

sys/src/games/gba/gba.c+0−474

This diff is large: its 475 lines aren’t shown here.

sys/src/games/gba/mem.c+0−639

This diff is large: its 640 lines aren’t shown here.

sys/src/games/gba/mkfile+0−16

This diff is large: its 17 lines aren’t shown here.

sys/src/games/gba/ppu.c+0−795

This diff is large: its 796 lines aren’t shown here.

sys/src/games/gba/state.c+0−165

This diff is large: its 166 lines aren’t shown here.

sys/src/games/geigerstats.c+0−90

This diff is large: its 91 lines aren’t shown here.

sys/src/games/glendy.c+0−531

This diff is large: its 532 lines aren’t shown here.

sys/src/games/juggle.c+0−217

This diff is large: its 218 lines aren’t shown here.

sys/src/games/life.c+0−446

This diff is large: its 447 lines aren’t shown here.

sys/src/games/mahjongg/graphics.c+0−334

This diff is large: its 335 lines aren’t shown here.

sys/src/games/mahjongg/level.c+0−149

This diff is large: its 150 lines aren’t shown here.

sys/src/games/mahjongg/logic.c+0−99

This diff is large: its 100 lines aren’t shown here.

sys/src/games/mahjongg/mahjongg.c+0−233

This diff is large: its 234 lines aren’t shown here.

sys/src/games/mahjongg/mahjongg.h+0−114

This diff is large: its 115 lines aren’t shown here.

sys/src/games/mahjongg/mkfile+0−20

This diff is large: its 21 lines aren’t shown here.

sys/src/games/mandel.c+0−238

This diff is large: its 239 lines aren’t shown here.

sys/src/games/md/cpu.c+0−1181

This diff is large: its 1182 lines aren’t shown here.

sys/src/games/md/dat.h+0−97

This diff is large: its 98 lines aren’t shown here.

sys/src/games/md/fns.h+0−20

This diff is large: its 21 lines aren’t shown here.

sys/src/games/md/md.c+0−341

This diff is large: its 342 lines aren’t shown here.

sys/src/games/md/mem.c+0−437

This diff is large: its 438 lines aren’t shown here.

sys/src/games/md/mkfile+0−15

This diff is large: its 16 lines aren’t shown here.

sys/src/games/md/vdp.c+0−397

This diff is large: its 398 lines aren’t shown here.

sys/src/games/md/ym.c+0−454

This diff is large: its 455 lines aren’t shown here.

sys/src/games/md/z80.c+0−821

This diff is large: its 822 lines aren’t shown here.

sys/src/games/memo.c+0−392

This diff is large: its 393 lines aren’t shown here.

sys/src/games/midi.c+0−250

This diff is large: its 251 lines aren’t shown here.

sys/src/games/mines/LICENCE+0−340

This diff is large: its 341 lines aren’t shown here.

sys/src/games/mines/README+0−31

This diff is large: its 32 lines aren’t shown here.

sys/src/games/mines/digit0.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit0.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit1.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit1.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit2.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit2.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit3.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit3.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit4.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit4.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit5.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit5.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit6.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit6.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit7.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit7.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit8.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit8.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/digit9.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/digit9.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty0.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty0.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty1.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty1.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty2.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty2.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty3.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty3.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty4.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty4.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty5.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty5.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty6.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty6.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty7.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty7.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/empty8.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/empty8.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/explosion.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/explosion.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/fault.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/fault.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/game.c+0−144

This diff is large: its 145 lines aren’t shown here.

sys/src/games/mines/game.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/mark.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/mark.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/mined.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/mined.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/mines.c+0−764

This diff is large: its 765 lines aren’t shown here.

sys/src/games/mines/mkfile+0−61

This diff is large: its 62 lines aren’t shown here.

sys/src/games/mines/mouse.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/mouse.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/move.c+0−144

This diff is large: its 145 lines aren’t shown here.

sys/src/games/mines/move.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/oops.c+0−144

This diff is large: its 145 lines aren’t shown here.

sys/src/games/mines/oops.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/pictures/digit0.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit1.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit2.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit3.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit4.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit5.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit6.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit7.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit8.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/digit9.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/empty0.raw+0−1

This diff is large: its 2 lines aren’t shown here.

sys/src/games/mines/pictures/empty1.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/empty2.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/empty3.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/empty4.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/empty5.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/empty6.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/empty7.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/empty8.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/explosion.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/fault.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/game.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/mark.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/mined.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/mouse.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/move.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/oops.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/push.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/query.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/sign.raw+0−0

Binary file not shown.

sys/src/games/mines/pictures/unknown.raw+0−1

This diff is large: its 2 lines aren’t shown here.

sys/src/games/mines/pictures/win.raw+0−0

Binary file not shown.

sys/src/games/mines/push.c+0−144

This diff is large: its 145 lines aren’t shown here.

sys/src/games/mines/push.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/query.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/query.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/sign.c+0−70

This diff is large: its 71 lines aren’t shown here.

sys/src/games/mines/sign.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/unknown.c+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mines/unknown.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mines/win.c+0−144

This diff is large: its 145 lines aren’t shown here.

sys/src/games/mines/win.h+0−23

This diff is large: its 24 lines aren’t shown here.

sys/src/games/mkfile+0−69

This diff is large: its 70 lines aren’t shown here.

sys/src/games/mole.c+0−249

This diff is large: its 250 lines aren’t shown here.

sys/src/games/music/Readme+0−12

This diff is large: its 13 lines aren’t shown here.

sys/src/games/music/debug.h+0−13

This diff is large: its 14 lines aren’t shown here.

sys/src/games/music/icon/next.bit+0−0

Binary file not shown.

sys/src/games/music/icon/pause.bit+0−0

Binary file not shown.

sys/src/games/music/icon/play.bit+0−0

Binary file not shown.

sys/src/games/music/icon/prev.bit+0−0

Binary file not shown.

sys/src/games/music/icon/question.bit+0−0

Binary file not shown.

sys/src/games/music/icon/root.bit+0−0

Binary file not shown.

sys/src/games/music/icon/skull.bit+0−0

Binary file not shown.

sys/src/games/music/icon/stop.bit+0−0

Binary file not shown.

sys/src/games/music/icon/trash.bit+0−0

Binary file not shown.

sys/src/games/music/juke.rc+0−57

This diff is large: its 58 lines aren’t shown here.

sys/src/games/music/jukebox/client.c+0−157

This diff is large: its 158 lines aren’t shown here.

sys/src/games/music/jukebox/client.h+0−10

This diff is large: its 11 lines aren’t shown here.

sys/src/games/music/jukebox/colors.c+0−120

This diff is large: its 121 lines aren’t shown here.

sys/src/games/music/jukebox/colors.h+0−30

This diff is large: its 31 lines aren’t shown here.

sys/src/games/music/jukebox/mk.dep+0−4

This diff is large: its 5 lines aren’t shown here.

sys/src/games/music/jukebox/mkfile+0−16

This diff is large: its 17 lines aren’t shown here.

sys/src/games/music/jukebox/music.c+0−1091

This diff is large: its 1092 lines aren’t shown here.

sys/src/games/music/jukebox/playlist.c+0−297

This diff is large: its 298 lines aren’t shown here.

sys/src/games/music/jukebox/playlist.h+0−26

This diff is large: its 27 lines aren’t shown here.

sys/src/games/music/jukefs/catset.c+0−152

This diff is large: its 153 lines aren’t shown here.

sys/src/games/music/jukefs/catset.h+0−8

This diff is large: its 9 lines aren’t shown here.

sys/src/games/music/jukefs/fs.c+0−757

This diff is large: its 758 lines aren’t shown here.

sys/src/games/music/jukefs/mk.dep+0−6

This diff is large: its 7 lines aren’t shown here.

sys/src/games/music/jukefs/mkfile+0−18

This diff is large: its 19 lines aren’t shown here.

sys/src/games/music/jukefs/object.h+0−117

This diff is large: its 118 lines aren’t shown here.

sys/src/games/music/jukefs/parse.c+0−616

This diff is large: its 617 lines aren’t shown here.

sys/src/games/music/jukefs/parse.h+0−15

This diff is large: its 16 lines aren’t shown here.

sys/src/games/music/jukefs/print.c+0−489

This diff is large: its 490 lines aren’t shown here.

sys/src/games/music/jukefs/print.h+0−6

This diff is large: its 7 lines aren’t shown here.

sys/src/games/music/jukefs/search.c+0−44

This diff is large: its 45 lines aren’t shown here.

sys/src/games/music/jukefs/search.h+0−5

This diff is large: its 6 lines aren’t shown here.

sys/src/games/music/jukefs/server.c+0−214

This diff is large: its 215 lines aren’t shown here.

sys/src/games/music/mkfile+0−51

This diff is large: its 52 lines aren’t shown here.

sys/src/games/music/mkinc+0−9

This diff is large: its 10 lines aren’t shown here.

sys/src/games/music/playlistfs/boilerplate.c+0−100

This diff is large: its 101 lines aren’t shown here.

sys/src/games/music/playlistfs/fs.c+0−892

This diff is large: its 893 lines aren’t shown here.

sys/src/games/music/playlistfs/main.c+0−94

This diff is large: its 95 lines aren’t shown here.

sys/src/games/music/playlistfs/mk.dep+0−5

This diff is large: its 6 lines aren’t shown here.

sys/src/games/music/playlistfs/mkfile+0−16

This diff is large: its 17 lines aren’t shown here.

sys/src/games/music/playlistfs/player.c+0−373

This diff is large: its 374 lines aren’t shown here.

sys/src/games/music/playlistfs/playlist.h+0−147

This diff is large: its 148 lines aren’t shown here.

sys/src/games/music/playlistfs/playplumb.c+0−20

This diff is large: its 21 lines aren’t shown here.

sys/src/games/music/playlistfs/volume.c+0−91

This diff is large: its 92 lines aren’t shown here.

sys/src/games/music/readcd+0−46

This diff is large: its 47 lines aren’t shown here.

sys/src/games/nes/apu.c+0−309

This diff is large: its 310 lines aren’t shown here.

sys/src/games/nes/cpu.c+0−453

This diff is large: its 454 lines aren’t shown here.

sys/src/games/nes/dat.h+0−108

This diff is large: its 109 lines aren’t shown here.

sys/src/games/nes/fns.h+0−16

This diff is large: its 17 lines aren’t shown here.

sys/src/games/nes/joynes+0−33

This diff is large: its 34 lines aren’t shown here.

sys/src/games/nes/mem.c+0−557

This diff is large: its 558 lines aren’t shown here.

sys/src/games/nes/mkfile+0−15

This diff is large: its 16 lines aren’t shown here.

sys/src/games/nes/nes.c+0−337

This diff is large: its 338 lines aren’t shown here.

sys/src/games/nes/ppu.c+0−344

This diff is large: its 345 lines aren’t shown here.

sys/src/games/nes/state.c+0−145

This diff is large: its 146 lines aren’t shown here.

sys/src/games/packet.c+0−435

This diff is large: its 436 lines aren’t shown here.

sys/src/games/snes/cpu.c+0−1052

This diff is large: its 1053 lines aren’t shown here.

sys/src/games/snes/dat.h+0−84

This diff is large: its 85 lines aren’t shown here.

sys/src/games/snes/dsp.c+0−647

This diff is large: its 648 lines aren’t shown here.

sys/src/games/snes/fns.h+0−30

This diff is large: its 31 lines aren’t shown here.

sys/src/games/snes/mem.c+0−655

This diff is large: its 656 lines aren’t shown here.

sys/src/games/snes/mkfile+0−16

This diff is large: its 17 lines aren’t shown here.

sys/src/games/snes/ppu.c+0−954

This diff is large: its 955 lines aren’t shown here.

sys/src/games/snes/snes.c+0−412

This diff is large: its 413 lines aren’t shown here.

sys/src/games/snes/spc.c+0−748

This diff is large: its 749 lines aren’t shown here.

sys/src/games/snes/state.c+0−194

This diff is large: its 195 lines aren’t shown here.

sys/src/games/sokoban/README+0−22

This diff is large: its 23 lines aren’t shown here.

sys/src/games/sokoban/animation.c+0−60

This diff is large: its 61 lines aren’t shown here.

sys/src/games/sokoban/graphics.c+0−124

This diff is large: its 125 lines aren’t shown here.

sys/src/games/sokoban/level.c+0−101

This diff is large: its 102 lines aren’t shown here.

sys/src/games/sokoban/mkfile+0−21

This diff is large: its 22 lines aren’t shown here.

sys/src/games/sokoban/move.c+0−136

This diff is large: its 137 lines aren’t shown here.

sys/src/games/sokoban/route.c+0−280

This diff is large: its 281 lines aren’t shown here.

sys/src/games/sokoban/sokoban.c+0−378

This diff is large: its 379 lines aren’t shown here.

sys/src/games/sokoban/sokoban.h+0−119

This diff is large: its 120 lines aren’t shown here.

sys/src/games/sudoku/game.c+0−436

This diff is large: its 437 lines aren’t shown here.

sys/src/games/sudoku/levels.c+0−200

This diff is large: its 201 lines aren’t shown here.

sys/src/games/sudoku/mkfile+0−18

This diff is large: its 19 lines aren’t shown here.

sys/src/games/sudoku/sudoku.c+0−422

This diff is large: its 423 lines aren’t shown here.

sys/src/games/sudoku/sudoku.h+0−55

This diff is large: its 56 lines aren’t shown here.

sys/src/games/xs.c+0−891

This diff is large: its 892 lines aren’t shown here.

sys/src/games/xs.h+0−24

This diff is large: its 25 lines aren’t shown here.

sys/src/mkfile+1−1

This diff is large: its 9 lines aren’t shown here.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t