IOWA 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (502) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTORS +14 -0
  3. data/README.md +23 -0
  4. data/RELEASE_NOTES +77 -0
  5. data/ToDo +21 -0
  6. data/components/CRUDList/CRUDList.html +13 -0
  7. data/components/CRUDList/CRUDList.iwa +136 -0
  8. data/components/Content/Content.html +0 -0
  9. data/components/Content/Content.iwa +143 -0
  10. data/components/Content/example/README +9 -0
  11. data/components/Content/example/cgi/iowa.cgi +10 -0
  12. data/components/Content/example/demo.rb +30 -0
  13. data/components/Content/example/doc/index.html +7 -0
  14. data/components/Content/example/iowa/Content.html +1 -0
  15. data/components/Content/example/iowa/Content.iwa +1 -0
  16. data/components/Content/example/iowa/Main.html +6 -0
  17. data/components/Content/example/iowa/Main.iwa +3 -0
  18. data/components/Content/example/iowa/_content/body +7 -0
  19. data/components/Content/example/iowa/_content/body2 +3 -0
  20. data/components/Content/example/iowa/_content/title +2 -0
  21. data/components/Content/example/iowa/app.cnf +8 -0
  22. data/components/Content/example/iowa/app.rb +8 -0
  23. data/components/Content/example/webrick.rb +38 -0
  24. data/components/Include/Include.html +1 -0
  25. data/components/Include/Include.iwa +30 -0
  26. data/components/Include/readme +5 -0
  27. data/components/JumpTo/JumpTo.html +8 -0
  28. data/components/JumpTo/JumpTo.iwa +8 -0
  29. data/components/JumpTo/readme +6 -0
  30. data/doc/Architecture.txt +6 -0
  31. data/doc/History.txt +33 -0
  32. data/doc/StandardDispatcher.txt +19 -0
  33. data/examples/blog/README +1 -0
  34. data/examples/hello_world/README +17 -0
  35. data/examples/hello_world/htdocs/hello_world_html.html +24 -0
  36. data/examples/hello_world/htdocs/hello_world_ruby.html +41 -0
  37. data/examples/hello_world/iowa/HelloWorld.html +14 -0
  38. data/examples/hello_world/iowa/HelloWorld.iwa +31 -0
  39. data/examples/hello_world/iowa/Index.html +16 -0
  40. data/examples/hello_world/iowa/Index.iwa +5 -0
  41. data/examples/hello_world/iowa/iowa_hello_world.cnf +19 -0
  42. data/examples/hello_world/iowa/iowa_hello_world.rb +5 -0
  43. data/examples/hello_world/iowa/mapfile.cnf +6 -0
  44. data/examples/hw1/iowa/Main.html +1 -0
  45. data/examples/hw1/iowa/README +9 -0
  46. data/examples/hw1/iowa/hw.rb +4 -0
  47. data/examples/hw2/iowa/Main.html +10 -0
  48. data/examples/hw2/iowa/Main.iwa +7 -0
  49. data/examples/hw2/iowa/README +16 -0
  50. data/examples/hw2/iowa/hw.rb +4 -0
  51. data/examples/hw3/iowa/Main.html +11 -0
  52. data/examples/hw3/iowa/Main.iwa +7 -0
  53. data/examples/hw3/iowa/README +22 -0
  54. data/examples/hw3/iowa/hw.rb +4 -0
  55. data/examples/hw4/iowa/Greetings.html +10 -0
  56. data/examples/hw4/iowa/Greetings.iwa +9 -0
  57. data/examples/hw4/iowa/Main.html +12 -0
  58. data/examples/hw4/iowa/Main.iwa +10 -0
  59. data/examples/hw4/iowa/README +28 -0
  60. data/examples/hw4/iowa/hw.rb +4 -0
  61. data/examples/hw5/iowa/Footer.html +2 -0
  62. data/examples/hw5/iowa/Greetings.html +4 -0
  63. data/examples/hw5/iowa/Greetings.iwa +12 -0
  64. data/examples/hw5/iowa/Header.html +6 -0
  65. data/examples/hw5/iowa/Main.html +12 -0
  66. data/examples/hw5/iowa/Main.iwa +13 -0
  67. data/examples/hw5/iowa/README +16 -0
  68. data/examples/hw5/iowa/hw.rb +4 -0
  69. data/examples/template_server/iowa/Content.iwa +121 -0
  70. data/examples/template_server/iowa/Content.view +0 -0
  71. data/examples/template_server/iowa/DBContentDispatcher.rb +112 -0
  72. data/examples/template_server/iowa/DBContentPage.html +3 -0
  73. data/examples/template_server/iowa/DBContentPage.iwa +85 -0
  74. data/examples/template_server/iowa/app.cnf +13 -0
  75. data/examples/template_server/iowa/app.rb +5 -0
  76. data/ext/Classifier/classifier.c +256 -0
  77. data/ext/Classifier/ext_help.h +14 -0
  78. data/ext/Classifier/extconf.rb +5 -0
  79. data/ext/Classifier/tst.h +40 -0
  80. data/ext/Classifier/tst_cleanup.c +24 -0
  81. data/ext/Classifier/tst_delete.c +146 -0
  82. data/ext/Classifier/tst_grow_node_free_list.c +38 -0
  83. data/ext/Classifier/tst_init.c +41 -0
  84. data/ext/Classifier/tst_insert.c +192 -0
  85. data/ext/Classifier/tst_search.c +68 -0
  86. data/ext/http11/README +11 -0
  87. data/ext/http11/ext_help.h +15 -0
  88. data/ext/http11/extconf.rb +5 -0
  89. data/ext/http11/http11.c +534 -0
  90. data/ext/http11/http11.c.dif +422 -0
  91. data/ext/http11/http11_parser.c +1243 -0
  92. data/ext/http11/http11_parser.c.dif +193 -0
  93. data/ext/http11/http11_parser.h +49 -0
  94. data/ext/http11/http11_parser.h.dif +20 -0
  95. data/ext/http11/http11_parser.rl +192 -0
  96. data/ext/httpmachine/Makefile +149 -0
  97. data/ext/httpmachine/extconf.rb +33 -0
  98. data/ext/httpmachine/http.cpp +430 -0
  99. data/ext/httpmachine/http.h +156 -0
  100. data/ext/httpmachine/rubyhttp.cpp +165 -0
  101. data/external/mime-types/LICENCE +18 -0
  102. data/external/mime-types/README +46 -0
  103. data/external/mime-types/doc/classes/MIME.html +120 -0
  104. data/external/mime-types/doc/classes/MIME/InvalidContentType.html +119 -0
  105. data/external/mime-types/doc/classes/MIME/Type.html +866 -0
  106. data/external/mime-types/doc/classes/MIME/Type.src/M000010.html +22 -0
  107. data/external/mime-types/doc/classes/MIME/Type.src/M000011.html +18 -0
  108. data/external/mime-types/doc/classes/MIME/Type.src/M000012.html +19 -0
  109. data/external/mime-types/doc/classes/MIME/Type.src/M000013.html +18 -0
  110. data/external/mime-types/doc/classes/MIME/Type.src/M000014.html +26 -0
  111. data/external/mime-types/doc/classes/MIME/Type.src/M000015.html +33 -0
  112. data/external/mime-types/doc/classes/MIME/Type.src/M000016.html +27 -0
  113. data/external/mime-types/doc/classes/MIME/Type.src/M000017.html +35 -0
  114. data/external/mime-types/doc/classes/MIME/Type.src/M000018.html +34 -0
  115. data/external/mime-types/doc/classes/MIME/Type.src/M000019.html +24 -0
  116. data/external/mime-types/doc/classes/MIME/Type.src/M000020.html +38 -0
  117. data/external/mime-types/doc/classes/MIME/Type.src/M000021.html +22 -0
  118. data/external/mime-types/doc/classes/MIME/Type.src/M000022.html +18 -0
  119. data/external/mime-types/doc/classes/MIME/Type.src/M000023.html +18 -0
  120. data/external/mime-types/doc/classes/MIME/Type.src/M000024.html +18 -0
  121. data/external/mime-types/doc/classes/MIME/Type.src/M000025.html +18 -0
  122. data/external/mime-types/doc/classes/MIME/Type.src/M000026.html +18 -0
  123. data/external/mime-types/doc/classes/MIME/Type.src/M000027.html +18 -0
  124. data/external/mime-types/doc/classes/MIME/Type.src/M000028.html +18 -0
  125. data/external/mime-types/doc/classes/MIME/Type.src/M000029.html +18 -0
  126. data/external/mime-types/doc/classes/MIME/Type.src/M000030.html +19 -0
  127. data/external/mime-types/doc/classes/MIME/Type.src/M000031.html +26 -0
  128. data/external/mime-types/doc/classes/MIME/Types.html +459 -0
  129. data/external/mime-types/doc/classes/MIME/Types.src/M000001.html +19 -0
  130. data/external/mime-types/doc/classes/MIME/Types.src/M000002.html +32 -0
  131. data/external/mime-types/doc/classes/MIME/Types.src/M000003.html +21 -0
  132. data/external/mime-types/doc/classes/MIME/Types.src/M000004.html +18 -0
  133. data/external/mime-types/doc/classes/MIME/Types.src/M000005.html +26 -0
  134. data/external/mime-types/doc/classes/MIME/Types.src/M000006.html +18 -0
  135. data/external/mime-types/doc/classes/MIME/Types.src/M000007.html +18 -0
  136. data/external/mime-types/doc/classes/MIME/Types.src/M000008.html +18 -0
  137. data/external/mime-types/doc/classes/MIME/Types.src/M000009.html +18 -0
  138. data/external/mime-types/doc/created.rid +1 -0
  139. data/external/mime-types/doc/files/ChangeLog.html +320 -0
  140. data/external/mime-types/doc/files/README.html +145 -0
  141. data/external/mime-types/doc/files/lib/mime/types_rb.html +101 -0
  142. data/external/mime-types/doc/fr_class_index.html +30 -0
  143. data/external/mime-types/doc/fr_file_index.html +29 -0
  144. data/external/mime-types/doc/fr_method_index.html +57 -0
  145. data/external/mime-types/doc/index.html +24 -0
  146. data/external/mime-types/doc/rdoc-style.css +208 -0
  147. data/external/mime-types/lib/mime/types.rb +1558 -0
  148. data/external/package.rb +672 -0
  149. data/external/test_support.rb +95 -0
  150. data/external/tmail/README +7 -0
  151. data/external/tmail/tmail.rb +4 -0
  152. data/external/tmail/tmail/address.rb +222 -0
  153. data/external/tmail/tmail/base64.rb +52 -0
  154. data/external/tmail/tmail/compat.rb +39 -0
  155. data/external/tmail/tmail/config.rb +50 -0
  156. data/external/tmail/tmail/encode.rb +447 -0
  157. data/external/tmail/tmail/header.rb +895 -0
  158. data/external/tmail/tmail/info.rb +14 -0
  159. data/external/tmail/tmail/loader.rb +1 -0
  160. data/external/tmail/tmail/mail.rb +869 -0
  161. data/external/tmail/tmail/mailbox.rb +386 -0
  162. data/external/tmail/tmail/mbox.rb +1 -0
  163. data/external/tmail/tmail/net.rb +260 -0
  164. data/external/tmail/tmail/obsolete.rb +123 -0
  165. data/external/tmail/tmail/parser.rb +1475 -0
  166. data/external/tmail/tmail/parser.y +372 -0
  167. data/external/tmail/tmail/port.rb +356 -0
  168. data/external/tmail/tmail/scanner.rb +17 -0
  169. data/external/tmail/tmail/scanner_r.rb +243 -0
  170. data/external/tmail/tmail/stringio.rb +256 -0
  171. data/external/tmail/tmail/textutils.rb +197 -0
  172. data/external/tmail/tmail/tmail.rb +1 -0
  173. data/external/tmail/tmail/utils.rb +23 -0
  174. data/external/win32-process/README +133 -0
  175. data/external/win32-process/lib/win32/process.rb +561 -0
  176. data/external/windows-pr/README +145 -0
  177. data/external/windows-pr/doc/conversion_guide.txt +25 -0
  178. data/external/windows-pr/lib/windows/clipboard.rb +72 -0
  179. data/external/windows-pr/lib/windows/console.rb +323 -0
  180. data/external/windows-pr/lib/windows/device_io.rb +88 -0
  181. data/external/windows-pr/lib/windows/directory.rb +80 -0
  182. data/external/windows-pr/lib/windows/error.rb +313 -0
  183. data/external/windows-pr/lib/windows/eventlog.rb +120 -0
  184. data/external/windows-pr/lib/windows/file.rb +349 -0
  185. data/external/windows-pr/lib/windows/filesystem.rb +16 -0
  186. data/external/windows-pr/lib/windows/handle.rb +31 -0
  187. data/external/windows-pr/lib/windows/library.rb +76 -0
  188. data/external/windows-pr/lib/windows/limits.rb +13 -0
  189. data/external/windows-pr/lib/windows/memory.rb +117 -0
  190. data/external/windows-pr/lib/windows/msvcrt/buffer.rb +48 -0
  191. data/external/windows-pr/lib/windows/msvcrt/file.rb +18 -0
  192. data/external/windows-pr/lib/windows/msvcrt/string.rb +46 -0
  193. data/external/windows-pr/lib/windows/national.rb +557 -0
  194. data/external/windows-pr/lib/windows/path.rb +296 -0
  195. data/external/windows-pr/lib/windows/pipe.rb +77 -0
  196. data/external/windows-pr/lib/windows/process.rb +171 -0
  197. data/external/windows-pr/lib/windows/registry.rb +238 -0
  198. data/external/windows-pr/lib/windows/security.rb +89 -0
  199. data/external/windows-pr/lib/windows/service.rb +183 -0
  200. data/external/windows-pr/lib/windows/shell.rb +88 -0
  201. data/external/windows-pr/lib/windows/sound.rb +52 -0
  202. data/external/windows-pr/lib/windows/synchronize.rb +161 -0
  203. data/external/windows-pr/lib/windows/system_info.rb +70 -0
  204. data/external/windows-pr/lib/windows/unicode.rb +138 -0
  205. data/external/windows-pr/lib/windows/window.rb +22 -0
  206. data/iowa.gemspec +45 -0
  207. data/microprojects/DiskCache/LICENSE +28 -0
  208. data/microprojects/DiskCache/README +17 -0
  209. data/microprojects/DiskCache/external/package.rb +608 -0
  210. data/microprojects/DiskCache/external/test_support.rb +8 -0
  211. data/microprojects/DiskCache/setup.rb +22 -0
  212. data/microprojects/DiskCache/src/iowa/Association.rb +67 -0
  213. data/microprojects/DiskCache/src/iowa/Constants.rb +159 -0
  214. data/microprojects/DiskCache/src/iowa/DiskStore.rb +377 -0
  215. data/microprojects/DiskCache/src/iowa/Hash.rb +63 -0
  216. data/microprojects/DiskCache/src/iowa/Lockfile.rb +575 -0
  217. data/microprojects/DiskCache/src/iowa/Mutex.rb +142 -0
  218. data/microprojects/DiskCache/src/iowa/caches/DiskCache.rb +605 -0
  219. data/microprojects/DiskCache/src/iowa/caches/LRUCache.rb +287 -0
  220. data/microprojects/DiskCache/test/TC_DiskCache.rb +218 -0
  221. data/microprojects/LRUCache/LICENSE +28 -0
  222. data/microprojects/LRUCache/README +13 -0
  223. data/microprojects/LRUCache/external/package.rb +608 -0
  224. data/microprojects/LRUCache/external/test_support.rb +8 -0
  225. data/microprojects/LRUCache/setup.rb +22 -0
  226. data/microprojects/LRUCache/src/iowa/Association.rb +57 -0
  227. data/microprojects/LRUCache/src/iowa/Constants.rb +159 -0
  228. data/microprojects/LRUCache/src/iowa/Hash.rb +63 -0
  229. data/microprojects/LRUCache/src/iowa/Mutex.rb +129 -0
  230. data/microprojects/LRUCache/src/iowa/caches/LRUCache.rb +287 -0
  231. data/microprojects/LRUCache/test/TC_LRUCache.rb +65 -0
  232. data/microprojects/LinkedList/LICENSE +28 -0
  233. data/microprojects/LinkedList/README +13 -0
  234. data/microprojects/LinkedList/external/package.rb +608 -0
  235. data/microprojects/LinkedList/external/test_support.rb +8 -0
  236. data/microprojects/LinkedList/setup.rb +22 -0
  237. data/microprojects/LinkedList/src/iowa/LinkedList.rb +165 -0
  238. data/microprojects/LinkedList/test/TC_LinkedList.rb +42 -0
  239. data/microprojects/README +8 -0
  240. data/setup.rb +116 -0
  241. data/share/iowa/app_skeleton/Main.html +8 -0
  242. data/share/iowa/app_skeleton/Main.iwa +15 -0
  243. data/share/iowa/app_skeleton/app.cnf +48 -0
  244. data/share/iowa/app_skeleton/app.rb +58 -0
  245. data/share/iowa/app_skeleton/models/model.rb +49 -0
  246. data/src/ihc.rb +223 -0
  247. data/src/iowa.cgi +29 -0
  248. data/src/iowa.rb +637 -0
  249. data/src/iowa/AbstractCache.rb +96 -0
  250. data/src/iowa/AcceptLanguage.rb +76 -0
  251. data/src/iowa/Application.rb +928 -0
  252. data/src/iowa/ApplicationStats.rb +72 -0
  253. data/src/iowa/Association.rb +67 -0
  254. data/src/iowa/BindingsParser.rb +62 -0
  255. data/src/iowa/Breakpoint.rb +273 -0
  256. data/src/iowa/CSS.rb +564 -0
  257. data/src/iowa/Client.rb +192 -0
  258. data/src/iowa/Component.rb +405 -0
  259. data/src/iowa/ComponentProxy.rb +26 -0
  260. data/src/iowa/Config.rb +21 -0
  261. data/src/iowa/Constants.rb +226 -0
  262. data/src/iowa/Context.rb +218 -0
  263. data/src/iowa/ContextLogger.rb +16 -0
  264. data/src/iowa/DbPool.rb +222 -0
  265. data/src/iowa/DetachedComponent.rb +18 -0
  266. data/src/iowa/Dispatcher.rb +27 -0
  267. data/src/iowa/DynamicElements.rb +471 -0
  268. data/src/iowa/Element.rb +100 -0
  269. data/src/iowa/Email.rb +287 -0
  270. data/src/iowa/Extensions/AllExtensions.rb +4 -0
  271. data/src/iowa/Extensions/Class.rb +94 -0
  272. data/src/iowa/Extensions/Date.rb +88 -0
  273. data/src/iowa/Extensions/DateTime.rb +88 -0
  274. data/src/iowa/Extensions/Hash.rb +22 -0
  275. data/src/iowa/Extensions/Kernel.rb +6 -0
  276. data/src/iowa/Extensions/Numeric.rb +47 -0
  277. data/src/iowa/Extensions/Object.rb +11 -0
  278. data/src/iowa/Extensions/String.rb +60 -0
  279. data/src/iowa/Extensions/Time.rb +89 -0
  280. data/src/iowa/Extensions/TimeExtensions.rb +6 -0
  281. data/src/iowa/Form.rb +368 -0
  282. data/src/iowa/Hash.rb +85 -0
  283. data/src/iowa/ISAAC.rb +175 -0
  284. data/src/iowa/ImageSize.rb +279 -0
  285. data/src/iowa/IowaComponentMixins.rb +7 -0
  286. data/src/iowa/JSON-lexer.rb +296 -0
  287. data/src/iowa/JSON-objects.rb +201 -0
  288. data/src/iowa/KeyValueCoding.rb +91 -0
  289. data/src/iowa/LinkedList.rb +175 -0
  290. data/src/iowa/Loader.rb +22 -0
  291. data/src/iowa/Lockfile.rb +575 -0
  292. data/src/iowa/Logger.rb +74 -0
  293. data/src/iowa/Monkey.rb +20 -0
  294. data/src/iowa/Mutex.rb +142 -0
  295. data/src/iowa/Policy.rb +70 -0
  296. data/src/iowa/Pool.rb +243 -0
  297. data/src/iowa/PrettyException.rb +1091 -0
  298. data/src/iowa/Request.rb +244 -0
  299. data/src/iowa/Response.rb +133 -0
  300. data/src/iowa/Session.rb +354 -0
  301. data/src/iowa/SessionStats.rb +78 -0
  302. data/src/iowa/String.rb +65 -0
  303. data/src/iowa/Tag.rb +101 -0
  304. data/src/iowa/TemplateParser.rb +236 -0
  305. data/src/iowa/Util.rb +314 -0
  306. data/src/iowa/Webcache.rb +122 -0
  307. data/src/iowa/caches/BiLevelCache.rb +65 -0
  308. data/src/iowa/caches/ClassLimitedCache.rb +67 -0
  309. data/src/iowa/caches/DiskCache.rb +609 -0
  310. data/src/iowa/caches/DiskStore.rb +380 -0
  311. data/src/iowa/caches/LRUCache-alternative.rb +155 -0
  312. data/src/iowa/caches/LRUCache.rb +290 -0
  313. data/src/iowa/caches/SimpleLRUCache.rb +112 -0
  314. data/src/iowa/dispatchers/StandardDispatcher.rb +396 -0
  315. data/src/iowa/dispatchers/StandardDispatcherWithClassifier.rb +93 -0
  316. data/src/iowa/js/iowa_jsonrpc.js +381 -0
  317. data/src/iowa/js/jsonrpc.js +187 -0
  318. data/src/iowa/js/jsonrpc_async.js +261 -0
  319. data/src/iowa/loaders/DiskLoader.rb +50 -0
  320. data/src/iowa/loggers/Analogger.rb +54 -0
  321. data/src/iowa/loggers/AsyncLogger.rb +54 -0
  322. data/src/iowa/loggers/BitBucket.rb +38 -0
  323. data/src/iowa/loggers/Log4R.rb +13 -0
  324. data/src/iowa/loggers/Log4rLogger.rb +48 -0
  325. data/src/iowa/loggers/Logger.rb +29 -0
  326. data/src/iowa/loggers/RubyLogger.rb +9 -0
  327. data/src/iowa/pools/DBConnectionPool.rb +53 -0
  328. data/src/iowa/request/Apache.rb +90 -0
  329. data/src/iowa/request/EMHybrid.rb +59 -0
  330. data/src/iowa/request/ENV.rb +80 -0
  331. data/src/iowa/request/FCGI.rb +68 -0
  332. data/src/iowa/request/HTTPMachine.rb +75 -0
  333. data/src/iowa/request/Mongrel.rb +68 -0
  334. data/src/iowa/request/WEBrick.rb +48 -0
  335. data/src/iowa/version.rb +3 -0
  336. data/src/iowa/webrick/HTTPServer.rb +43 -0
  337. data/src/iowa/webrick/WEBrickServlet.rb +28 -0
  338. data/src/iowa_fcgi_handler.rb +101 -0
  339. data/src/iowa_httpmachine.rb +141 -0
  340. data/src/iowa_hybrid.rb +193 -0
  341. data/src/iowa_hybrid_cluster.rb +231 -0
  342. data/src/iowa_mongrel.rb +136 -0
  343. data/src/iowa_webrick.rb +194 -0
  344. data/src/iowa_webrick_legacy.rb +104 -0
  345. data/src/mod_iowa.rb +104 -0
  346. data/tcss.rb +61 -0
  347. data/test/README.windows +12 -0
  348. data/test/TC_AcceptLanguage.rb +61 -0
  349. data/test/TC_AppConfig.rb +43 -0
  350. data/test/TC_AppConfig/cgi/iowa.cgi +7 -0
  351. data/test/TC_AppConfig/doc/index.html +1 -0
  352. data/test/TC_AppConfig/iowa/Main.html +4 -0
  353. data/test/TC_AppConfig/iowa/Main.iwa +17 -0
  354. data/test/TC_AppConfig/iowa/README +1 -0
  355. data/test/TC_AppConfig/iowa/app.cnf +19 -0
  356. data/test/TC_AppConfig/iowa/app.rb +8 -0
  357. data/test/TC_AppConfig/webrick.rb +38 -0
  358. data/test/TC_Association.rb +29 -0
  359. data/test/TC_BiLevelCache.rb +71 -0
  360. data/test/TC_CGI_Adaptor.rb +55 -0
  361. data/test/TC_CGI_Adaptor/cgi/iowa.cgi +7 -0
  362. data/test/TC_CGI_Adaptor/doc/index.html +1 -0
  363. data/test/TC_CGI_Adaptor/iowa/Main.html +8 -0
  364. data/test/TC_CGI_Adaptor/iowa/Main.iwa +14 -0
  365. data/test/TC_CGI_Adaptor/iowa/README +1 -0
  366. data/test/TC_CGI_Adaptor/iowa/app.cnf +8 -0
  367. data/test/TC_CGI_Adaptor/iowa/app.rb +8 -0
  368. data/test/TC_CGI_Adaptor/webrick.rb +38 -0
  369. data/test/TC_CSS.rb +660 -0
  370. data/test/TC_ClassLimitedCache.rb +89 -0
  371. data/test/TC_Classifier.rb +80 -0
  372. data/test/TC_DbPool.rb +127 -0
  373. data/test/TC_DiskCache.rb +218 -0
  374. data/test/TC_Hybrid.rb +58 -0
  375. data/test/TC_Hybrid/doc/thing.txt +1 -0
  376. data/test/TC_Hybrid/iowa/Main.html +3 -0
  377. data/test/TC_Hybrid/iowa/Main.iwa +7 -0
  378. data/test/TC_Hybrid/iowa/NewPage.html +1 -0
  379. data/test/TC_Hybrid/iowa/NewPage.iwa +5 -0
  380. data/test/TC_Hybrid/iowa/app.cnf +10 -0
  381. data/test/TC_Hybrid/iowa/app.rb +5 -0
  382. data/test/TC_IOWAFunctions/doc/Ajax1.html +1 -0
  383. data/test/TC_IOWAFunctions/doc/Ajax1.iwa +1 -0
  384. data/test/TC_IOWAFunctions/doc/index.html +1 -0
  385. data/test/TC_IOWAFunctions/doc/js/dojo.js +9686 -0
  386. data/test/TC_IOWAFunctions/iowa/Ajax1.html +40 -0
  387. data/test/TC_IOWAFunctions/iowa/Ajax1.iwa +23 -0
  388. data/test/TC_IOWAFunctions/iowa/AjaxWidget.iwa +19 -0
  389. data/test/TC_IOWAFunctions/iowa/AjaxWidget.view +22 -0
  390. data/test/TC_IOWAFunctions/iowa/DanielTest.html +9 -0
  391. data/test/TC_IOWAFunctions/iowa/DanielTest.iwa +10 -0
  392. data/test/TC_IOWAFunctions/iowa/IntervalWidget.html +1 -0
  393. data/test/TC_IOWAFunctions/iowa/IntervalWidget.iwa +14 -0
  394. data/test/TC_IOWAFunctions/iowa/Main.html +1 -0
  395. data/test/TC_IOWAFunctions/iowa/NestedRepeat1.html +12 -0
  396. data/test/TC_IOWAFunctions/iowa/NestedRepeat1.iwa +24 -0
  397. data/test/TC_IOWAFunctions/iowa/RPCResponse.iwa +7 -0
  398. data/test/TC_IOWAFunctions/iowa/RPCResponse.view +1 -0
  399. data/test/TC_IOWAFunctions/iowa/Repeat1.iwa +31 -0
  400. data/test/TC_IOWAFunctions/iowa/Repeat1.view +9 -0
  401. data/test/TC_IOWAFunctions/iowa/Repeat2.iwa +32 -0
  402. data/test/TC_IOWAFunctions/iowa/Repeat2.view +11 -0
  403. data/test/TC_IOWAFunctions/iowa/Repeat3.iwa +44 -0
  404. data/test/TC_IOWAFunctions/iowa/Repeat3.view +18 -0
  405. data/test/TC_IOWAFunctions/iowa/TesCon.html +1 -0
  406. data/test/TC_IOWAFunctions/iowa/TesCon.iwa +5 -0
  407. data/test/TC_IOWAFunctions/iowa/app.cnf +19 -0
  408. data/test/TC_IOWAFunctions/iowa/app.rb +9 -0
  409. data/test/TC_IOWAFunctions/iowa/mapfile.cnf +8 -0
  410. data/test/TC_ISAAC.rb +52 -0
  411. data/test/TC_ImageSize.rb +84 -0
  412. data/test/TC_ImageSize/img.bmp +0 -0
  413. data/test/TC_ImageSize/img.gif +0 -0
  414. data/test/TC_ImageSize/img.jpg +0 -0
  415. data/test/TC_ImageSize/img.pcx +0 -0
  416. data/test/TC_ImageSize/img.pgm +7144 -0
  417. data/test/TC_ImageSize/img.png +0 -0
  418. data/test/TC_ImageSize/img.ppm +0 -0
  419. data/test/TC_ImageSize/img.psd +0 -0
  420. data/test/TC_ImageSize/img.tiff +0 -0
  421. data/test/TC_ImageSize/img.xbm +22 -0
  422. data/test/TC_KeyValueCoding.rb +35 -0
  423. data/test/TC_LRUCache.rb +296 -0
  424. data/test/TC_LinkedList.rb +46 -0
  425. data/test/TC_Lockfile.rb +106 -0
  426. data/test/TC_Minimal.rb +45 -0
  427. data/test/TC_Minimal/app.cnf +8 -0
  428. data/test/TC_Minimal/cgi-bin/iowa.cgi +11 -0
  429. data/test/TC_Minimal/doc/index.html +1 -0
  430. data/test/TC_Minimal/iowa/Main.html +1 -0
  431. data/test/TC_Minimal/iowa/README +1 -0
  432. data/test/TC_Minimal/iowa/app.rb +3 -0
  433. data/test/TC_Minimal/webrick.rb +38 -0
  434. data/test/TC_Mongrel.rb +58 -0
  435. data/test/TC_Mongrel/doc/thing.txt +1 -0
  436. data/test/TC_Mongrel/iowa/Main.html +3 -0
  437. data/test/TC_Mongrel/iowa/Main.iwa +7 -0
  438. data/test/TC_Mongrel/iowa/NewPage.html +1 -0
  439. data/test/TC_Mongrel/iowa/NewPage.iwa +5 -0
  440. data/test/TC_Mongrel/iowa/app.cnf +10 -0
  441. data/test/TC_Mongrel/iowa/app.rb +5 -0
  442. data/test/TC_NoSubclass.rb +56 -0
  443. data/test/TC_NoSubclass/cgi/iowa.cgi +7 -0
  444. data/test/TC_NoSubclass/doc/index.html +1 -0
  445. data/test/TC_NoSubclass/iowa/Main.html +8 -0
  446. data/test/TC_NoSubclass/iowa/Main.iwa +14 -0
  447. data/test/TC_NoSubclass/iowa/README +1 -0
  448. data/test/TC_NoSubclass/iowa/app.cnf +8 -0
  449. data/test/TC_NoSubclass/iowa/app.rb +5 -0
  450. data/test/TC_NoSubclass/webrick.rb +38 -0
  451. data/test/TC_Pool.rb +139 -0
  452. data/test/TC_RenderedCache/doc/thing.txt +1 -0
  453. data/test/TC_RenderedCache/iowa/BigPage.html +1 -0
  454. data/test/TC_RenderedCache/iowa/BigPage.iwa +12 -0
  455. data/test/TC_RenderedCache/iowa/Main.html +3 -0
  456. data/test/TC_RenderedCache/iowa/Main.iwa +7 -0
  457. data/test/TC_RenderedCache/iowa/NewPage.html +1 -0
  458. data/test/TC_RenderedCache/iowa/NewPage.iwa +11 -0
  459. data/test/TC_RenderedCache/iowa/app.cnf +13 -0
  460. data/test/TC_RenderedCache/iowa/app.rb +5 -0
  461. data/test/TC_RenderedCache/iowa/mapfile.map +4 -0
  462. data/test/TC_ResourceURL.rb +73 -0
  463. data/test/TC_ResourceURL/iowa/Main.html +2 -0
  464. data/test/TC_ResourceURL/iowa/Main.iwa +10 -0
  465. data/test/TC_ResourceURL/iowa/app.cnf +10 -0
  466. data/test/TC_ResourceURL/iowa/app.rb +5 -0
  467. data/test/TC_SimpleDetached.rb +41 -0
  468. data/test/TC_StandardDispatcher.rb +362 -0
  469. data/test/TC_StandardDispatcherWithClassifier.rb +358 -0
  470. data/test/TC_String.rb +24 -0
  471. data/test/TC_Tag.rb +41 -0
  472. data/test/TC_Webrick.rb +56 -0
  473. data/test/TC_Webrick/doc/thing.txt +1 -0
  474. data/test/TC_Webrick/iowa/Main.html +3 -0
  475. data/test/TC_Webrick/iowa/Main.iwa +7 -0
  476. data/test/TC_Webrick/iowa/NewPage.html +1 -0
  477. data/test/TC_Webrick/iowa/NewPage.iwa +5 -0
  478. data/test/TC_Webrick/iowa/app.cnf +10 -0
  479. data/test/TC_Webrick/iowa/app.rb +5 -0
  480. data/test/tc_template.rb +15 -0
  481. data/test/tests.conf +19 -0
  482. data/utils/CVS/Entries +3 -0
  483. data/utils/CVS/Repository +1 -0
  484. data/utils/CVS/Root +1 -0
  485. data/utils/QuickCert-1.0.2.tar.gz +0 -0
  486. data/utils/QuickCert-1.0.2/InstalledFiles +7 -0
  487. data/utils/QuickCert-1.0.2/MANIFEST +10 -0
  488. data/utils/QuickCert-1.0.2/Makefile +15 -0
  489. data/utils/QuickCert-1.0.2/README +56 -0
  490. data/utils/QuickCert-1.0.2/bin/QuickCert +355 -0
  491. data/utils/QuickCert-1.0.2/config.save +12 -0
  492. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/README +60 -0
  493. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_c.rb +26 -0
  494. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_s.rb +35 -0
  495. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/qc_config +21 -0
  496. data/utils/QuickCert-1.0.2/lib/QuickCert/defaults.rb +28 -0
  497. data/utils/QuickCert-1.0.2/setup.rb +1312 -0
  498. data/utils/iowa_apps +422 -0
  499. data/utils/smtp_sink.rb +9 -0
  500. data/utils/startup_template.cnf +27 -0
  501. data/utils/startup_template.rb +73 -0
  502. metadata +551 -0
@@ -0,0 +1,197 @@
1
+ #
2
+ # textutils.rb
3
+ #
4
+ # Copyright (c) 1998-2004 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU Lesser General Public License version 2.1.
9
+ #
10
+
11
+ module TMail
12
+
13
+ class SyntaxError < StandardError; end
14
+
15
+
16
+ module TextUtils
17
+
18
+ private
19
+
20
+ def new_boundary
21
+ 'mimepart_' + random_tag()
22
+ end
23
+
24
+ @@uniq = 0
25
+
26
+ def random_tag
27
+ @@uniq += 1
28
+ t = Time.now
29
+ sprintf('%x%x_%x%x%d%x',
30
+ t.to_i, t.tv_usec,
31
+ $$, Thread.current.id, @@uniq, rand(255))
32
+ end
33
+
34
+ aspecial = '()<>[]:;.@\\,"'
35
+ tspecial = '()<>[];:@\\,"/?='
36
+ lwsp = " \t\r\n"
37
+ control = '\x00-\x1f\x7f-\xff'
38
+
39
+ ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{lwsp}]/n
40
+ PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n
41
+ TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{lwsp}]/n
42
+ CONTROL_CHAR = /[#{control}]/n
43
+ RFC2231_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{lwsp}\*\'\%]/n
44
+
45
+ def atom_safe?(str)
46
+ ATOM_UNSAFE !~ str
47
+ end
48
+
49
+ def quote_atom(str)
50
+ (ATOM_UNSAFE =~ str) ? dquote(str) : str
51
+ end
52
+
53
+ def quote_phrase(str)
54
+ (PHRASE_UNSAFE =~ str) ? dquote(str) : str
55
+ end
56
+
57
+ def token_safe?(str)
58
+ TOKEN_UNSAFE !~ str
59
+ end
60
+
61
+ def quote_token(str)
62
+ (TOKEN_UNSAFE =~ str) ? dquote(str) : str
63
+ end
64
+
65
+ def dquote(str)
66
+ '"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"'
67
+ end
68
+ private :dquote
69
+
70
+ def join_domain(arr)
71
+ arr.map {|i| (/\A\[.*\]\z/ =~ i) ? i : quote_atom(i) }.join('.')
72
+ end
73
+
74
+ ZONESTR_TABLE = {
75
+ 'jst' => 9 * 60,
76
+ 'eet' => 2 * 60,
77
+ 'bst' => 1 * 60,
78
+ 'met' => 1 * 60,
79
+ 'gmt' => 0,
80
+ 'utc' => 0,
81
+ 'ut' => 0,
82
+ 'nst' => -(3 * 60 + 30),
83
+ 'ast' => -4 * 60,
84
+ 'edt' => -4 * 60,
85
+ 'est' => -5 * 60,
86
+ 'cdt' => -5 * 60,
87
+ 'cst' => -6 * 60,
88
+ 'mdt' => -6 * 60,
89
+ 'mst' => -7 * 60,
90
+ 'pdt' => -7 * 60,
91
+ 'pst' => -8 * 60,
92
+ 'a' => -1 * 60,
93
+ 'b' => -2 * 60,
94
+ 'c' => -3 * 60,
95
+ 'd' => -4 * 60,
96
+ 'e' => -5 * 60,
97
+ 'f' => -6 * 60,
98
+ 'g' => -7 * 60,
99
+ 'h' => -8 * 60,
100
+ 'i' => -9 * 60,
101
+ # j not use
102
+ 'k' => -10 * 60,
103
+ 'l' => -11 * 60,
104
+ 'm' => -12 * 60,
105
+ 'n' => 1 * 60,
106
+ 'o' => 2 * 60,
107
+ 'p' => 3 * 60,
108
+ 'q' => 4 * 60,
109
+ 'r' => 5 * 60,
110
+ 's' => 6 * 60,
111
+ 't' => 7 * 60,
112
+ 'u' => 8 * 60,
113
+ 'v' => 9 * 60,
114
+ 'w' => 10 * 60,
115
+ 'x' => 11 * 60,
116
+ 'y' => 12 * 60,
117
+ 'z' => 0 * 60
118
+ }
119
+
120
+ def timezone_string_to_unixtime(str)
121
+ if m = /([\+\-])(\d\d?)(\d\d)/.match(str)
122
+ sec = (m[2].to_i * 60 + m[3].to_i) * 60
123
+ (m[1] == '-') ? -sec : sec
124
+ else
125
+ min = ZONESTR_TABLE[str.downcase] or
126
+ raise SyntaxError, "wrong timezone format '#{str}'"
127
+ min * 60
128
+ end
129
+ end
130
+
131
+ WDAY = %w( Sun Mon Tue Wed Thu Fri Sat TMailBUG )
132
+ MONTH = %w( TMailBUG Jan Feb Mar Apr May Jun
133
+ Jul Aug Sep Oct Nov Dec TMailBUG )
134
+
135
+ def time2str(tm)
136
+ # [ruby-list:7928]
137
+ gmt = Time.at(tm.to_i)
138
+ gmt.gmtime
139
+ offset = tm.to_i - Time.local(*gmt.to_a[0,6].reverse).to_i
140
+
141
+ # DO NOT USE strftime: setlocale() breaks it
142
+ sprintf '%s, %s %s %d %02d:%02d:%02d %+.2d%.2d',
143
+ WDAY[tm.wday], tm.mday, MONTH[tm.month],
144
+ tm.year, tm.hour, tm.min, tm.sec,
145
+ *(offset / 60).divmod(60)
146
+ end
147
+
148
+ MESSAGE_ID = /<[^\@>]+\@[^>\@]+>/
149
+
150
+ def message_id?(str)
151
+ MESSAGE_ID =~ str
152
+ end
153
+
154
+ def mime_encoded?(str)
155
+ /=\?[^\s?=]+\?[QB]\?[^\s?=]+\?=/i =~ str
156
+ end
157
+
158
+ def decode_params(hash)
159
+ new = Hash.new
160
+ encoded = nil
161
+ hash.each do |key, value|
162
+ if m = /\*(?:(\d+)\*)?\z/.match(key)
163
+ ((encoded ||= {})[m.pre_match] ||= [])[(m[1] || 0).to_i] = value
164
+ else
165
+ new[key] = to_kcode(value)
166
+ end
167
+ end
168
+ if encoded
169
+ encoded.each do |key, strings|
170
+ new[key] = decode_RFC2231(strings.join(''))
171
+ end
172
+ end
173
+
174
+ new
175
+ end
176
+
177
+ NKF_FLAGS = {
178
+ 'EUC' => '-e -m',
179
+ 'SJIS' => '-s -m'
180
+ }
181
+
182
+ def to_kcode(str)
183
+ flag = NKF_FLAGS[$KCODE] or return str
184
+ NKF.nkf(flag, str)
185
+ end
186
+
187
+ RFC2231_ENCODED = /\A(?:iso-2022-jp|euc-jp|shift_jis|us-ascii)?'[a-z]*'/in
188
+
189
+ def decode_RFC2231(str)
190
+ m = RFC2231_ENCODED.match(str) or return str
191
+ NKF.nkf(NKF_FLAGS[$KCODE],
192
+ m.post_match.gsub(/%[\da-f]{2}/in) {|s| s[1,2].hex.chr })
193
+ end
194
+
195
+ end
196
+
197
+ end
@@ -0,0 +1 @@
1
+ require 'tmail'
@@ -0,0 +1,23 @@
1
+ #
2
+ # utils.rb
3
+ #
4
+ # Copyright (c) 1998-2004 Minero Aoki
5
+ #
6
+ # This program is free software.
7
+ # You can distribute/modify this program under the terms of
8
+ # the GNU Lesser General Public License version 2.1.
9
+ #
10
+
11
+ require 'tmail/textutils'
12
+ require 'socket'
13
+
14
+ module TMail
15
+
16
+ extend TextUtils
17
+
18
+ def TMail.new_message_id(fqdn = nil)
19
+ fqdn ||= ::Socket.gethostname
20
+ "<#{random_tag()}@#{fqdn}.tmail>"
21
+ end
22
+
23
+ end
@@ -0,0 +1,133 @@
1
+ This is a stripped down package of Daniel Berger's win32-process library.
2
+ This is version 0.5.0.
3
+
4
+ The original can be found at Rubyforge at:
5
+
6
+ http://rubyforge.org/projects/win32utils
7
+
8
+ This library will be installed only if it is not already present on the
9
+ appropriate platform. The main setup.rb for IOWA takes care of it, including
10
+ generation of ri documentation.
11
+
12
+ Below is the original README
13
+
14
+ -----
15
+
16
+ = Description
17
+ This package provides the fork, wait, wait2, waitpid, and waitpid2 methods
18
+ for MS Windows. In addition, it provides a different implementation of the
19
+ kill method.
20
+
21
+ = Prerequisites
22
+ Ruby 1.8.2 or later.
23
+ The 'windows-pr' package 0.5.2 or later.
24
+ The 'sys-proctable' package 0.7.0 or later (test suite only).
25
+
26
+ = Supported Platforms
27
+ This code is supported on Windows NT, Windows 2000 or Windows XP Pro only.
28
+ It may work on Windows XP Home, but it is not officially supported for that
29
+ platform.
30
+
31
+ = Installation Instructions
32
+ == Manual Installation
33
+ ruby test/tc_process.rb (optional)
34
+ ruby install.rb
35
+ == Gem Installation
36
+ ruby win32-process.gemspec
37
+ win32-process-X.Y.Z-mswin32.gem
38
+
39
+ = Synopsis
40
+ require 'win32/process'
41
+
42
+ Process.fork{
43
+ 3.times{
44
+ puts 'In the child'
45
+ sleep 1
46
+ }
47
+ }
48
+
49
+ Process.wait
50
+ puts 'Done'
51
+
52
+ = Developer's Notes
53
+ == The fork and wait methods
54
+ The fork method is emulated on Win32 by spawning a another Ruby process
55
+ against $PROGRAM_NAME via the CreateProcess() Win32 API function. It will
56
+ use its parent's environment and starting directory.
57
+
58
+ The various wait methods are a wrapper for the WaitForSingleObject() or
59
+ WaitForMultipleObjects() Win32 API functions, for the wait* and waitpid*
60
+ methods, respectively. In the case of wait2 and waitpid2, the exit value
61
+ is returned via the GetExitCodeProcess() Win32API function.
62
+
63
+ For now the waitpid and waitpid2 calls do not accept a second argument.
64
+ That's because we haven't yet determined if there's a signal we should
65
+ allow to be sent.
66
+
67
+ IMPORTANT!
68
+ Note that because fork is calling CreateProcess($PROGRAM_NAME), it will
69
+ start again from the top of the script instead of from the point of the
70
+ call. We will try to address this in a future release, if possible.
71
+
72
+ == The kill method
73
+ Initially, the kill method will try to get a HANDLE on the PID using the
74
+ OpenProcess() function. If that succeeds, we know the process is running.
75
+
76
+ In the event of signal 2 or signal 3, the GenerateConsoleCtrlEvent()
77
+ function is used to send a signal to that process. These will not kill
78
+ GUI processes. It will not (currently) send a signal to remote
79
+ processes.
80
+
81
+ In the event of signal 1 or 4-8, the CreateRemoteThread() function is used
82
+ after the HANDLE's process has been identified to create a thread
83
+ within that process. The ExitProcess() function is then sent to that
84
+ thread.
85
+
86
+ In the event of signal 9, the TerminateProcess() function is called. This
87
+ will almost certainly kill the process, but doesn't give the process a
88
+ chance to necessarily do any cleanup it might otherwise do.
89
+
90
+ == Differences between Ruby's kill and the Win32 Utils kill
91
+ Ruby does not currently use the CreateRemoteThread() + ExitProcess()
92
+ approach which is, according to everything I've read, a cleaner approach.
93
+ This includes not only online research but also Jeffrey Richter's
94
+ "Advanced Windows Programming, 3rd Edition."
95
+
96
+ Also, the way kill handles multiple pids works slightly differently (and
97
+ better IMHO) in the Win32 Utils version than the way Ruby currently
98
+ provides.
99
+
100
+ The reason Process.kill was originally added, in case anyone cares for
101
+ historical trivia, is that Ruby 1.6.x did not support Process.kill on
102
+ Windows at all.
103
+
104
+ == Notes
105
+ It is unlikely you will be able to kill system processes with this module.
106
+ It's probably better that you don't.
107
+
108
+ == Known Bugs
109
+ None known (though please see the +Details+ section for quirks). Any
110
+ bugs should be reported on the project page at
111
+ http://rubyforge.org/projects/win32utils.
112
+
113
+ == Future Plans
114
+ Train Process.fork to execute from the point of the call rather than the
115
+ top of the script (if possible).
116
+
117
+ Other suggestions welcome.
118
+
119
+ == License
120
+ Ruby's
121
+
122
+ == Copyright
123
+ (C) 2003-2006 Daniel J. Berger
124
+ All Rights Reserved
125
+
126
+ == Warranty
127
+ This package is provided "as is" and without any express or
128
+ implied warranties, including, without limitation, the implied
129
+ warranties of merchantability and fitness for a particular purpose.
130
+
131
+ == Author(s)
132
+ Park Heesob
133
+ Daniel J. Berger
@@ -0,0 +1,561 @@
1
+ require 'windows/error'
2
+ require 'windows/process'
3
+ require 'windows/synchronize'
4
+ require 'windows/handle'
5
+ require 'windows/library'
6
+ require 'windows/console'
7
+ require 'windows/window'
8
+
9
+ class ProcessError < RuntimeError; end
10
+
11
+ module Process
12
+ WIN32_PROCESS_VERSION = '0.5.0'
13
+
14
+ include Windows::Process
15
+ include Windows::Error
16
+ include Windows::Library
17
+ include Windows::Console
18
+ include Windows::Handle
19
+ include Windows::Synchronize
20
+ include Windows::Window
21
+ extend Windows::Error
22
+ extend Windows::Process
23
+ extend Windows::Synchronize
24
+ extend Windows::Handle
25
+ extend Windows::Library
26
+ extend Windows::Console
27
+
28
+ # Used by Process.create
29
+ ProcessInfo = Struct.new("ProcessInfo",
30
+ :process_handle,
31
+ :thread_handle,
32
+ :process_id,
33
+ :thread_id
34
+ )
35
+
36
+ @child_pids = [] # Static variable used for Process.fork
37
+ @i = -1 # Static variable used for Process.fork
38
+
39
+ # Waits for the given child process to exit and returns that pid.
40
+ #
41
+ # Note that the $? (Process::Status) global variable is NOT set. This
42
+ # may be addressed in a future release.
43
+ #
44
+ def waitpid(pid)
45
+ exit_code = [0].pack('L')
46
+ handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
47
+
48
+ if handle == INVALID_HANDLE_VALUE
49
+ raise ProcessError, get_last_error
50
+ end
51
+
52
+ # TODO: update the $? global variable (if/when possible)
53
+ status = WaitForSingleObject(handle, INFINITE)
54
+
55
+ unless GetExitCodeProcess(handle, exit_code)
56
+ raise ProcessError, get_last_error
57
+ end
58
+
59
+ CloseHandle(handle)
60
+ @child_pids.delete(pid)
61
+
62
+ # TODO: update the $? global variable (if/when possible)
63
+ exit_code = exit_code.unpack('L').first
64
+
65
+ pid
66
+ end
67
+
68
+ # Waits for the given child process to exit and returns an array containing
69
+ # the process id and the exit status.
70
+ #
71
+ # Note that the $? (Process::Status) global variable is NOT set. This
72
+ # may be addressed in a future release.
73
+ #
74
+ def waitpid2(pid)
75
+ exit_code = [0].pack('L')
76
+ handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
77
+
78
+ if handle == INVALID_HANDLE_VALUE
79
+ raise ProcessError, get_last_error
80
+ end
81
+
82
+ # TODO: update the $? global variable (if/when possible)
83
+ status = WaitForSingleObject(handle, INFINITE)
84
+
85
+ unless GetExitCodeProcess(handle, exit_code)
86
+ raise ProcessError, get_last_error
87
+ end
88
+
89
+ CloseHandle(handle)
90
+ @child_pids.delete(pid)
91
+
92
+ # TODO: update the $? global variable (if/when possible)
93
+ exit_code = exit_code.unpack('L').first
94
+
95
+ [pid, status]
96
+ end
97
+
98
+ # Sends the given +signal+ to an array of process id's. The +signal+ may
99
+ # be any value from 0 to 9, or the special strings 'SIGINT' (or 'INT'),
100
+ # 'SIGBRK' (or 'BRK') and 'SIGKILL' (or 'KILL'). An array of successfully
101
+ # killed pids is returned.
102
+ #
103
+ # Signal 0 merely tests if the process is running without killing it.
104
+ # Signal 2 sends a CTRL_C_EVENT to the process.
105
+ # Signal 3 sends a CTRL_BRK_EVENT to the process.
106
+ # Signal 9 kills the process in a harsh manner.
107
+ # Signals 1 and 4-8 kill the process in a nice manner.
108
+ #
109
+ # SIGINT/INT corresponds to signal 2
110
+ # SIGBRK/BRK corresponds to signal 3
111
+ # SIGKILL/KILL corresponds to signal 9
112
+ #
113
+ # Signals 2 and 3 only affect console processes, and then only if the
114
+ # process was created with the CREATE_NEW_PROCESS_GROUP flag.
115
+ #
116
+ def kill(signal, *pids)
117
+ case signal
118
+ when 'SIGINT', 'INT'
119
+ signal = 2
120
+ when 'SIGBRK', 'BRK'
121
+ signal = 3
122
+ when 'SIGKILL', 'KILL'
123
+ signal = 9
124
+ when 0..9
125
+ # Do nothing
126
+ else
127
+ raise ProcessError, "Invalid signal '#{signal}'"
128
+ end
129
+
130
+ killed_pids = []
131
+
132
+ pids.each{ |pid|
133
+ # Send the signal to the current process if the pid is zero
134
+ if pid == 0
135
+ pid = Process.pid
136
+ end
137
+
138
+ # No need for full access if the signal is zero
139
+ if signal == 0
140
+ access = PROCESS_QUERY_INFORMATION|PROCESS_VM_READ
141
+ handle = OpenProcess(access, 0 , pid)
142
+ else
143
+ handle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
144
+ end
145
+
146
+ case signal
147
+ when 0
148
+ if handle != 0
149
+ killed_pids.push(pid)
150
+ CloseHandle(handle)
151
+ else
152
+ # If ERROR_ACCESS_DENIED is returned, we know it's running
153
+ if GetLastError() == ERROR_ACCESS_DENIED
154
+ killed_pids.push(pid)
155
+ else
156
+ raise ProcessError, get_last_error
157
+ end
158
+ end
159
+ when 2
160
+ if GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid)
161
+ killed_pids.push(pid)
162
+ end
163
+ when 3
164
+ if GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid)
165
+ killed_pids.push(pid)
166
+ end
167
+ when 9
168
+ if TerminateProcess(handle, pid)
169
+ CloseHandle(handle)
170
+ killed_pids.push(pid)
171
+ @child_pids.delete(pid)
172
+ else
173
+ raise ProcessError, get_last_error
174
+ end
175
+ else
176
+ if handle != 0
177
+ thread_id = [0].pack('L')
178
+ dll = 'kernel32'
179
+ proc = 'ExitProcess'
180
+
181
+ thread = CreateRemoteThread(
182
+ handle,
183
+ 0,
184
+ 0,
185
+ GetProcAddress(GetModuleHandle(dll), proc),
186
+ 0,
187
+ 0,
188
+ thread_id
189
+ )
190
+
191
+ if thread
192
+ WaitForSingleObject(thread, 5)
193
+ CloseHandle(handle)
194
+ killed_pids.push(pid)
195
+ @child_pids.delete(pid)
196
+ else
197
+ CloseHandle(handle)
198
+ raise ProcessError, get_last_error
199
+ end
200
+ else
201
+ raise ProcessError, get_last_error
202
+ end
203
+ @child_pids.delete(pid)
204
+ end
205
+ }
206
+
207
+ killed_pids
208
+ end
209
+
210
+ # Process.create(key => value, ...) => ProcessInfo
211
+ #
212
+ # This is a wrapper for the CreateProcess() function. It executes a process,
213
+ # returning a ProcessInfo struct. It accepts a hash as an argument.
214
+ # There are six primary keys:
215
+ #
216
+ # * app_name (mandatory)
217
+ # * inherit (default: false)
218
+ # * process_inherit (default: false)
219
+ # * thread_inherit (default: false)
220
+ # * creation_flags (default: 0)
221
+ # * cwd (default: Dir.pwd)
222
+ # * startup_info (default: nil)
223
+ # * environment (default: nil)
224
+ #
225
+ # Of these, the 'app_name' must be specified or an error is raised.
226
+ #
227
+ # The startup_info key takes a hash. Its keys are attributes that are
228
+ # part of the StartupInfo struct, and are generally only meaningful for
229
+ # GUI or console processes. See the documentation on CreateProcess()
230
+ # and the StartupInfo struct on MSDN for more information.
231
+ #
232
+ # * desktop
233
+ # * title
234
+ # * x
235
+ # * y
236
+ # * x_size
237
+ # * y_size
238
+ # * x_count_chars
239
+ # * y_count_chars
240
+ # * fill_attribute
241
+ # * sw_flags
242
+ # * startf_flags
243
+ #
244
+ # The relevant constants for 'creation_flags', 'sw_flags' and 'startf_flags'
245
+ # are included in the Windows::Process, Windows::Console and Windows::Window
246
+ # modules. These come with the windows-pr package, a prerequisite of this
247
+ # package.
248
+ #
249
+ # The ProcessInfo struct contains the following members:
250
+ #
251
+ # * process_handle - The handle to the newly created process
252
+ # * thread_handle - The handle to the primary thread of the newly created
253
+ # process.
254
+ # * process_id - Process ID.
255
+ # * thread_id - Thread ID.
256
+ #
257
+ def create(args)
258
+ raise TypeError unless args.kind_of?(Hash)
259
+
260
+ valid_keys = %w/
261
+ app_name inherit creation_flags cwd environment startup_info
262
+ thread_inherit process_inherit
263
+ /
264
+
265
+ valid_si_keys = %/
266
+ startf_flags desktop title x y x_size y_size x_count_chars
267
+ y_count_chars fill_attribute sw_flags stdin stdout stderr
268
+ /
269
+
270
+ # Set some default values
271
+ hash = {
272
+ 'inherit' => 0,
273
+ 'process_inherit' => 0,
274
+ 'thread_inherit' => 0,
275
+ 'creation_flags' => 0,
276
+ 'cwd' => 0
277
+ }
278
+ env = 0
279
+
280
+ # Validate the keys, and convert symbols and case to lowercase strings.
281
+ args.each{ |key, val|
282
+ key = key.to_s.downcase
283
+ unless valid_keys.include?(key)
284
+ raise ProcessError, "invalid key '#{key}'"
285
+ end
286
+
287
+ # Convert true to 1 and nil/false to 0.
288
+ case val
289
+ when true, false
290
+ hash[key] = val == false ? 0 : 1
291
+ when nil
292
+ hash[key] = 0 # Win32API no likey nil
293
+ else
294
+ hash[key] = val
295
+ end
296
+ }
297
+
298
+ si_hash = {}
299
+
300
+ # If the startup_info key is present, validate its subkeys
301
+ if hash['startup_info']
302
+ hash['startup_info'].each{ |key, val|
303
+ key = key.to_s.downcase
304
+ unless valid_si_keys.include?(key)
305
+ raise ProcessError, "invalid startup_info key '#{key}'"
306
+ end
307
+ si_hash[key] = val
308
+ }
309
+ end
310
+
311
+ # The +app_name+ key is mandatory
312
+ unless hash['app_name']
313
+ raise ProcessError, 'app_name must be specified'
314
+ end
315
+
316
+ # The environment string should be passed as a string of ';' separated
317
+ # paths.
318
+ if hash['environment']
319
+ env = hash['environment'].split(File::PATH_SEPARATOR) << 0.chr
320
+ env = [env.join("\0")].pack('p*').unpack('L').first
321
+ end
322
+
323
+ startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
324
+ startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL')
325
+ procinfo = [0,0,0,0].pack('LLLL')
326
+
327
+ # Process SECURITY_ATTRIBUTE structure
328
+ process_security = 0
329
+ if hash['process_inherit?']
330
+ process_security = [0,0,0].pack('LLL')
331
+ process_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE)
332
+ process_security[8,4] = [hash['process_inherit?']].pack('L')
333
+ end
334
+
335
+ # Thread SECURITY_ATTRIBUTE structure
336
+ thread_security = 0
337
+ if hash['thread_security?']
338
+ thread_security = [0,0,0].pack('LLL')
339
+ thread_security[0,4] = [12].pack('L') # sizeof(SECURITY_ATTRIBUTE)
340
+ thread_security[8,4] = [hash['thread_inherit?']].pack('L')
341
+ end
342
+
343
+ # The bytes not covered here are reserved (null)
344
+ unless si_hash.empty?
345
+ startinfo[0,4] = [startinfo.size].pack('L')
346
+ startinfo[8,4] = [si_hash['desktop']].pack('p*') if si_hash['desktop']
347
+ startinfo[12,4] = [si_hash['title']].pack('p*') if si_hash['title']
348
+ startinfo[16,4] = [si_hash['x']].pack('L') if si_hash['x']
349
+ startinfo[20,4] = [si_hash['y']].pack('L') if si_hash['y']
350
+ startinfo[24,4] = [si_hash['x_size']].pack('L') if si_hash['x_size']
351
+ startinfo[28,4] = [si_hash['y_size']].pack('L') if si_hash['y_size']
352
+ startinfo[32,4] = [si_hash['x_count_chars']].pack('L') if si_hash['x_count_chars']
353
+ startinfo[36,4] = [si_hash['y_count_chars']].pack('L') if si_hash['y_count_chars']
354
+ startinfo[40,4] = [si_hash['fill_attribute']].pack('L') if si_hash['fill_attribute']
355
+ startinfo[44,4] = [si_hash['startf_flags']].pack('L') if si_hash['startf_flags']
356
+ startinfo[48,2] = [si_hash['sw_flags']].pack('S') if si_hash['sw_flags']
357
+ startinfo[56,4] = [si_hash['stdin']].pack('L') if si_hash['stdin']
358
+ startinfo[60,4] = [si_hash['stdout']].pack('L') if si_hash['stdout']
359
+ startinfo[64,4] = [si_hash['stderr']].pack('L') if si_hash['stderr']
360
+ end
361
+
362
+ rv = CreateProcess(
363
+ 0, # App name
364
+ hash['app_name'], # Command line
365
+ process_security, # Process attributes
366
+ thread_security, # Thread attributes
367
+ hash['inherit'], # Inherit handles?
368
+ hash['creation_flags'], # Creation flags
369
+ env, # Environment
370
+ hash['cwd'], # Working directory
371
+ startinfo, # Startup Info
372
+ procinfo # Process Info
373
+ )
374
+
375
+ if rv == 0
376
+ raise ProcessError, "CreateProcess() failed: %", get_last_error
377
+ end
378
+
379
+ ProcessInfo.new(
380
+ procinfo[0,4].unpack('L').first, # hProcess
381
+ procinfo[4,4].unpack('L').first, # hThread
382
+ procinfo[8,4].unpack('L').first, # hProcessId
383
+ procinfo[12,4].unpack('L').first # hThreadId
384
+ )
385
+ end
386
+
387
+ # Waits for any child process to exit and returns the process id of that
388
+ # child.
389
+ #
390
+ # Note that the $? (Process::Status) global variable is NOT set. This
391
+ # may be addressed in a future release.
392
+ #--
393
+ # The GetProcessId() function is not defined in Windows 2000 or earlier
394
+ # so we have to do some extra work for those platforms.
395
+ #
396
+ def wait
397
+ handles = []
398
+
399
+ # Windows 2000 or earlier
400
+ unless defined? GetProcessId
401
+ pids = []
402
+ end
403
+
404
+ @child_pids.each_with_index{ |pid, i|
405
+ handles[i] = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
406
+
407
+ if handles[i] == INVALID_HANDLE_VALUE
408
+ err = "unable to get HANDLE on process associated with pid #{pid}"
409
+ raise ProcessError, err
410
+ end
411
+
412
+ unless defined? GetProcessId
413
+ pids[i] = pid
414
+ end
415
+ }
416
+
417
+ wait = WaitForMultipleObjects(
418
+ handles.size,
419
+ handles.pack('L*'),
420
+ 0,
421
+ INFINITE
422
+ )
423
+
424
+ if wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + @child_pids.size - 1
425
+ index = wait - WAIT_OBJECT_0
426
+ handle = handles[index]
427
+
428
+ if defined? GetProcessId
429
+ pid = GetProcessId(handle)
430
+ else
431
+ pid = pids[index]
432
+ end
433
+
434
+ @child_pids.delete(pid)
435
+ handles.each{ |handle| CloseHandle(handle) }
436
+ return pid
437
+ end
438
+
439
+ nil
440
+ end
441
+
442
+ # Waits for any child process to exit and returns an array containing the
443
+ # process id and the exit status of that child.
444
+ #
445
+ # Note that the $? (Process::Status) global variable is NOT set. This
446
+ # may be addressed in a future release.
447
+ #--
448
+ # The GetProcessId() function is not defined in Windows 2000 or earlier
449
+ # so we have to do some extra work for those platforms.
450
+ #
451
+ def wait2
452
+ handles = []
453
+
454
+ # Windows 2000 or earlier
455
+ unless defined? GetProcessId
456
+ pids = []
457
+ end
458
+
459
+ @child_pids.each_with_index{ |pid, i|
460
+ handles[i] = OpenProcess(PROCESS_ALL_ACCESS, 0, pid)
461
+
462
+ if handles[i] == INVALID_HANDLE_VALUE
463
+ err = "unable to get HANDLE on process associated with pid #{pid}"
464
+ raise ProcessError, err
465
+ end
466
+
467
+ unless defined? GetProcessId
468
+ pids[i] = pid
469
+ end
470
+ }
471
+
472
+ wait = WaitForMultipleObjects(
473
+ handles.size,
474
+ handles.pack('L*'),
475
+ 0,
476
+ INFINITE
477
+ )
478
+
479
+ if wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + @child_pids.size - 1
480
+ index = wait - WAIT_OBJECT_0
481
+ handle = handles[index]
482
+
483
+ if defined? GetProcessId
484
+ pid = GetProcessId(handle)
485
+ else
486
+ pid = pids[index]
487
+ end
488
+
489
+ exit_code = [0].pack('l')
490
+ unless GetExitCodeProcess(handle, exit_code)
491
+ raise get_last_error
492
+ end
493
+
494
+ @child_pids.delete(pid)
495
+
496
+ handles.each{ |handle| CloseHandle(handle) }
497
+ return [pid, exit_code.unpack('l').first]
498
+ end
499
+
500
+ nil
501
+ end
502
+
503
+ # Creates the equivalent of a subshell via the CreateProcess() function.
504
+ # This behaves in a manner that is similar, but not identical to, the
505
+ # Kernel.fork method for Unix.
506
+ #
507
+ def fork
508
+ last_arg = ARGV.last
509
+
510
+ # Look for the 'child#xxx' tag
511
+ if last_arg =~ /child#\d+/
512
+ @i += 1
513
+ num = last_arg.split('#').last.to_i
514
+ if num == @i
515
+ if block_given?
516
+ status = 0
517
+ begin
518
+ yield
519
+ rescue Exception
520
+ status = -1 # Any non-zero result is failure
521
+ ensure
522
+ return status
523
+ end
524
+ end
525
+ return nil
526
+ else
527
+ return false
528
+ end
529
+ end
530
+
531
+ # Tag the command with the word 'child#xxx' to distinguish it
532
+ # from the calling process.
533
+ cmd = 'ruby -I "' + $LOAD_PATH.join(File::PATH_SEPARATOR) << '" "'
534
+ cmd << File.expand_path($PROGRAM_NAME) << '" ' << ARGV.join(' ')
535
+ cmd << ' child#' << @child_pids.length.to_s
536
+
537
+ startinfo = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
538
+ startinfo = startinfo.pack('LLLLLLLLLLLLSSLLLL')
539
+ procinfo = [0,0,0,0].pack('LLLL')
540
+
541
+ rv = CreateProcess(0, cmd, 0, 0, 1, 0, 0, 0, startinfo, procinfo)
542
+
543
+ if rv == 0
544
+ raise ProcessError, get_last_error
545
+ end
546
+
547
+ pid = procinfo[8,4].unpack('L').first
548
+ @child_pids.push(pid)
549
+
550
+ pid
551
+ end
552
+
553
+ module_function :kill, :wait, :wait2, :waitpid, :waitpid2, :create, :fork
554
+ end
555
+
556
+ # Create a global fork method
557
+ module Kernel
558
+ def fork(&block)
559
+ Process.fork(&block)
560
+ end
561
+ end