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

13767 more lines aren’t shown here.

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