{"id":15096,"date":"2020-08-25T10:20:07","date_gmt":"2020-08-25T01:20:07","guid":{"rendered":"https:\/\/its-more.jp\/ja_jp\/?p=15096"},"modified":"2020-08-28T23:20:47","modified_gmt":"2020-08-28T14:20:47","slug":"gshell-0-2-1-%e2%88%92-%e3%83%84%e3%82%a4%e3%82%b9%e3%83%86%e3%83%83%e3%83%89%e3%82%b9%e3%83%88%e3%83%aa%e3%83%bc%e3%83%a0","status":"publish","type":"post","link":"https:\/\/its-more.jp\/ja_jp\/?p=15096","title":{"rendered":"GShell 0.2.1 \u2212 \u30c4\u30a4\u30b9\u30c8\u30b9\u30c8\u30ea\u30fc\u30e0"},"content":{"rendered":"\n<p>\u958b\u767a\uff1a\u6a5f\u80fdGShell\u3067\u30ea\u30e2\u30fc\u30c8\u30b3\u30de\u30f3\u30c9\u3092\u5b9f\u88c5\u3057\u3066\u308b\u6642\u306b\u601d\u3063\u305f\u306e\u3067\u3059\u304c\u3001\u3084\u306f\u308a\u4e00\u672c\u306e\u30b9\u30c8\u30ea\u30fc\u30e0\u4e0a\u3067\u30bd\u30d5\u30c8\u306bEOF\u3068\u3044\u3046\u304bEOR\u3092\u9001\u308b\u306e\u306f\u96e3\u3057\u3044\u304b\u306a\u3068\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1a\u306a\u306e\u3067\u5236\u5fa1\u7528\u3068\u306f\u5225\u306b\u6bce\u56deTCP\u3092\u5f35\u3063\u3066\u4f7f\u3044\u6368\u3066\u308b\u3068\u3044\u3046\u8a08\u753b\u3067\u3059\u3088\u306d\u3002FTP\u5f0f\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u305d\u308c\u3082\u307e\u305f\u91ce\u86ee\u3068\u3044\u3046\u304b\u3001\u5404\u30ec\u30a4\u30e4\u306b\u5f0a\u5bb3\u304c\u51fa\u308b\u3088\u3046\u306a\u4e88\u611f\u3082\u3059\u308b\u3059\u308b\u308f\u3051\u3067\u3059\u3002\u7279\u306b\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5c64\u3067\u4e2d\u7d99\u3059\u308b\u5834\u5408\u306b\u306f\u3001\u63a5\u7d9a\u306e\u78ba\u7acb\u306f\u4e00\u5927\u30a4\u30d9\u30f3\u30c8\u3067\u3059\u304b\u3089\u3001\u8a8d\u8a3c\u3082\u3059\u308b\u3067\u3057\u3087\u3046\u3057\u30ed\u30b0\u3082\u53d6\u308b\u3002\u30a8\u30f3\u30c9\u30fc\u30a8\u30f3\u30c9\u306b\u3057\u3066\u3082\u3001\u901a\u4fe1\u3092SSL\u3068\u304b\u3067\u6697\u53f7\u5316\u3059\u308b\u306a\u3089\u3001\u30cd\u30b4\u306b\u304b\u306a\u308a\u91cd\u3044\u51e6\u7406\u3068\u3044\u3046\u304b\u9045\u5ef6\u304c\u751f\u3058\u308b\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a1KB\u7a0b\u5ea6\u306e\u4e0d\u63c3\u3044\u3067\u7d30\u304b\u3044\u30c7\u30fc\u30bf\u3092\u6bce\u79d210\b,000\u500b\u9001\u308c\u308b\u306e\u3092\u76ee\u6a19\u3068\u3059\u308b\u3068\u3057\u307e\u3059\u3002\u3053\u308c\u306f\u30cd\u30c3\u30c8\u306e\u30d0\u30f3\u30c9\u5e45\u7684\u306b\u306f10MB\/s\u3067\u305f\u3084\u3059\u3044\u3057\u3001\u30c7\u30fc\u30bf\u306e\u51fa\u3069\u3053\u308d\u304c\u30c7\u30a3\u30b9\u30af\u3067\u3042\u3063\u3066\u3082\u3001\u307e\u3042HDD\u306e\u5834\u5408\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fb\u30d5\u30a1\u30a4\u30eb\u306eopen\u306b\u5f8b\u901f\u3055\u308c\u3066\u72b6\u6cc1\u306b\u3088\u308b\u3067\u3057\u3087\u3046\u3051\u3069\u3001SSD\u306a\u3089\u697d\u52dd\u306e\u6570\u5024\u3067\u3057\u3087\u3046\u3002<\/p>\n\n\n\n<p>\u57fa\u76e4\uff1a\u3078\u306e\u304b\u3063\u3071\u3067\u3059\u306d\u3002HDD\u306b\u3057\u3066\u3082\u3001RAM\u4e0a\u306binode\u3068block\u304c\u6b8b\u3063\u3066\u308c\u3070\u3001\u554f\u984c\u306a\u3044\u3093\u3058\u3083\u306a\u3044\u3067\u3059\u304b\u3002\u983b\u7e41\u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b\u3088\u3046\u306a\u30d5\u30a1\u30a4\u30eb\u306a\u3089\u3002\u3061\u3087\u3063\u3068\u5b9f\u6e2c\u3057\u3066\u307f\u307e\u3059\u2026<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"648\" height=\"195\" src=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-10.49.10.png\" alt=\"\" class=\"wp-image-15102\" srcset=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-10.49.10.png 648w, https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-10.49.10-300x90.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure>\n\n\n\n<p>\u57fa\u76e4\uff1aGo\u306e\u30bd\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u69cb\u9020\u306f\u307e\u3042\u4e00\u4f8b\u3067\u3059\u3051\u3069\u3001du \u3067\u898b\u308b\u3068\u3001\u30c7\u30a3\u30ec\u30af\u30c8\u3092\u306a\u3081\u3066inode\u60c5\u5831\u3092\u53ce\u96c6\u3059\u308b\u3060\u3051\u306a\u3089\u30011\u79d2\u306b200,000\u30d5\u30a1\u30a4\u30eb\u306f\u30a4\u30b1\u307e\u3059\u300210,000\u306f\u697d\u52dd\u3067\u3059\u3002block\u307e\u3067\u8aad\u307f\u66f8\u304d\u3059\u308b\u3068\u306a\u308b\u3068\u3001tar\u306e\u4f8b\u3067\u306f\u30012,000\u30d5\u30a1\u30a4\u30eb\/\u79d2\u304f\u3089\u3044\u306b\u843d\u3061\u3066\u307e\u3059\u300210,000\u306f\u53b3\u3057\u3044\u3067\u3059\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1atar xf \u3088\u308a cf \u306e\u307b\u3046\u304c\u9045\u3044\u3068\u3044\u3046\u306e\u306f\u610f\u5916\u3067\u3059\u306d\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u5927\u534a\u306fOS\u6642\u9593\u307f\u305f\u3044\u3067\u3059\u306d\u3002\u3081\u3063\u3061\u3083stat\u3068\u304b\u3057\u3066\u308b\u3093\u3067\u3057\u3087\u3046\u304b\uff1f<\/p>\n\n\n\n<p>\u793e\u9577\uff1a\u3044\u305a\u308c\u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u3092\u30c8\u30ec\u30fc\u30b9\u3057\u3066\u8997\u304d\u307e\u3057\u3087\u3046\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u3067\u3082 GShell \u7248\u306e rsync \u3068\u3044\u3046\u304b mirror \u3067\u306e\u30d5\u30a1\u30a4\u30eb\u8ee2\u9001\u3067\u306f\u3001tar \u306f\u4f7f\u308f\u306a\u3044\u4e88\u5b9a\u3067\u3059\u3002\u305f\u3060 find \u76f8\u5f53\u306e\u5185\u90e8\u30b3\u30de\u30f3\u30c9\u3067\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u306a\u3081\u3066\u3001\u30d5\u30a1\u30a4\u30eb\u3092\u304b\u305f\u306f\u3057\u304b\u3089\u30e1\u30bf\u60c5\u5831\u3068\u3068\u3082\u306b\u6295\u3052\u308b\u3002\u3082\u3061\u308d\u3093 tar \u306e\u3088\u3046\u306a\u30d1\u30c7\u30a3\u30f3\u30b0\u3068\u304b\u7121\u3044\u3067\u3059\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u6bce\u79d210,000\u500b\u3068\u3044\u3046\u3053\u3068\u306f\u3001\u4e00\u500b\u3042\u305f\u308a0.1\u30df\u30ea\u79d2\u3067\u3059\u3002\u3053\u308c\u306fLAN\u3067\u3042\u3063\u3066\u3082\u3061\u3087\u3063\u3068\u53b3\u3057\u3044\u30ec\u30a4\u30c6\u30f3\u30b7\u3002\u9060\u9694\u306a\u3089250ms\u304b\u304b\u3063\u3066\u3057\u307e\u3046\u3053\u3068\u3082\u6709\u308b\u3068\u3044\u3046\u5b9f\u4f8b\u306f\u6211\u793e\u306e\u30d5\u30e9\u30f3\u30af\u30d5\u30eb\u30c8\u652f\u6240\u3068\u306e\u901a\u4fe1\u3067\u76ee\u306b\u3057\u3066\u3044\u308b\u3068\u3053\u308d\u3067\u3059\u3002TCP\u3092\u5f35\u3063\u3066\u30ea\u30af\u30a8\u30b9\u30c8\u3068\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u3059\u308b\u3060\u3051\u30671\u79d2\u304b\u304b\u308b\u4e8b\u306f\u5fc5\u5b9a\u3002\u6bce\u79d21\u500b\u3057\u304b\u9001\u308c\u306a\u3044\u3053\u3068\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u306a\u306e\u3067 GShell\u7248\u306e sync \u3067\u306f\u3001\u307e\u305a\u53d7\u3051\u53d6\u308a\u5074\u306e 10,000\uff0810K\uff09\u500b\u306e\u30d5\u30a1\u30a4\u30eb\u306estat\u3092\u9001\u308b\u3002\u30d5\u30a1\u30a4\u30eb\u540d\u304c\u53ef\u5909\u9577\u306a\u306e\u3067\u8aad\u3081\u306a\u3044\u3067\u3059\u304c\u3001\u4e00\u9023\u306e\u30d5\u30a1\u30a4\u30eb\u540d\u30c8\u30e9\u30d0\u30fc\u30b9\u306e\u4e2d\u306e\u76f8\u5bfe\u30d1\u30b9\u3067\u3001\u30d9\u30fc\u30b9\u30cd\u30fc\u30e0\u3060\u3051\u306b\u3067\u304d\u308b\u3002\u30d5\u30a1\u30a4\u30eb\u540d\u3068\u30e1\u30bf\u60c5\u5831\u542b\u3081\u306632\u30d0\u30a4\u30c8\u5e73\u5747\u304f\u3089\u3044\u3068\u3059\u308c\u3070\u3001320K\u30d0\u30a4\u30c8\u3002\u30d5\u30e9\u30f3\u30af\u30d5\u30eb\u30c8\u306e\u3088\u3046\u306b1MB\/s\u3067\u3042\u3063\u305f\u3068\u3057\u3066\u3082\u30010.3\u79d2\u3067\u3059\u3002\u3068\u3044\u3046\u304b\u3053\u308c\u306f\u3001\u30c7\u30fc\u30bf\u306e\u9001\u4fe1\u3068\u4e26\u884c\u3057\u3066\u9001\u3063\u3066\u3082\u826f\u3044\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u6b21\u306b\u53d7\u3051\u53d6\u308a\u5074\u306f\u81ea\u5206\u306e\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u3068\u6bd4\u8f03\u3057\u306a\u304c\u3089\u5909\u5316\u306e\u3042\u308b\u30d5\u30a1\u30a4\u30eb\u3060\u3051\u3092\u9001\u4fe1\u3059\u308b\u3002\u3053\u3053\u306f\u30e1\u30bf\u60c5\u5831\u3060\u3051\u3067\u6e08\u307e\u305b\u308b\u304b\u3001\u4e2d\u8eab\u306e\u30c0\u30a4\u30b8\u30a7\u30b9\u30c8\u307e\u3067\u542b\u3081\u308b\u304b\u3001\u601d\u6848\u306e\u3057\u3069\u3053\u308d\u3067\u3059\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1a\u4e2d\u8eab\u307e\u3067\u8aad\u3093\u3058\u3083\u3046\u3068 tar \u306e\u4f8b\u306e\u3088\u3046\u306b 2,000\u500b\/\u79d2\u306b\u843d\u3061\u3066\u3057\u307e\u3046\u304b\u3082\u77e5\u308c\u306a\u3044\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u3044\u3048\u3001\u3042\u308c\u306f tar \u304c\u9045\u3059\u304e\u3067\u3059\u3002GShell\u3067grep\u76f8\u5f53\u5185\u90e8\u30b3\u30de\u30f3\u30c9\u3092\u8a66\u3057\u305f\u6642\u306f\u3082\u3063\u3068\u9ad8\u901f\u3067\u3057\u305f\u3002\u3061\u3087\u3063\u3068\u3001 \u30c1\u30a7\u30c3\u30af\u30b5\u30e0\u3060\u3051\u53d6\u308b\u30b3\u30de\u30f3\u30c9\u3092\u4f5c\u3063\u3066\u8a66\u3057\u3066\u307f\u307e\u3059\u2026<\/p>\n\n\n\n<p class=\"has-text-align-center\">\uff0a\u3000\uff0a\u3000\uff0a<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u305d\u3046\u3044\u3046\u308f\u3051\u3067\u3001\u3044\u304f\u3064\u306f\u30c1\u30a7\u30c3\u30af\u30b5\u30e0\u65b9\u5f0f\u3092\u5b9f\u88c5\u3057\u3066\u6e2c\u3063\u3066\u307f\u307e\u3057\u305f\u3002\u307e\u305a\u3001Unix \u3067\u6614\u3088\u304f\u4f7f\u3063\u3066\u305f sum \u30b3\u30de\u30f3\u30c9\u306e\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u3002BSDsum \u3068\u547c\u3070\u308c\u3066\u308b\u3089\u3057\u3044\u3067\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"648\" height=\"263\" src=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.22.20.png\" alt=\"\" class=\"wp-image-15122\" srcset=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.22.20.png 648w, https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.22.20-300x122.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure>\n\n\n\n<p>\u57fa\u76e4\uff1a23,000\u30d5\u30a1\u30a4\u30eb\/\u79d2\u3001223MB\/s \u51fa\u3066\u307e\u3059\u306d\u3002HDD\u3067\u306f\u53b3\u3057\u3044\u3067\u3059\u304c\u3001SSD\u3067\u306a\u3089\u30a4\u30b1\u308b\u53ef\u80fd\u6027\u306e\u3042\u308b\u30b9\u30d4\u30fc\u30c9\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u6b21\u306f\u3001Go\u8a00\u8a9e\u306eCRC32\u30d1\u30c3\u30b1\u30fc\u30b8\u306b\u3088\u308bCRC32\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"648\" height=\"110\" src=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.26.27.png\" alt=\"\" class=\"wp-image-15124\" srcset=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.26.27.png 648w, https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.26.27-300x51.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure>\n\n\n\n<p>\u793e\u9577\uff1a\u3055\u3059\u304c\u306bCRC\u306e\u8a08\u7b97\u3067\u30e6\u30fc\u30b6CPU\u6642\u9593\u304c\u591a\u3044\u3067\u3059\u304c\u3001\u305d\u308c\u304c\u30cd\u30c3\u30af\u306b\u306f\u306a\u3089\u306a\u305d\u3046\u3067\u3059\u306d\u3002\u3068\u3044\u3046\u304b\u3001BSD sum \u3088\u308a\u901f\u3044\u3093\u3067\u3059\u304b\u2026<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u3061\u306a\u307f\u306b\u793e\u9577\u304c\u6614\u81ea\u4f5c\u3057\u305fCRC32\u3060\u3068\u300120MB\/s \u3067\u3057\u305f\u3002tar \u3068\u540c\u683c\u3067\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"648\" height=\"138\" src=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.44.42.png\" alt=\"\" class=\"wp-image-15128\" srcset=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.44.42.png 648w, https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.44.42-300x64.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure>\n\n\n\n<p>\u793e\u9577\uff1a(^-^;<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u6b21\u306b\u3001\u5358\u7d14\u306a\u8db3\u3057\u7b97\u3002\u307e\u3055\u306bsum\u3002SysV sum \u3068\u540c\u7cfb\u3067\u3059\u3002\u305f\u3060\u3057\u300164\u30d3\u30c3\u30c8\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"648\" height=\"110\" src=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.28.42.png\" alt=\"\" class=\"wp-image-15125\" srcset=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.28.42.png 648w, https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.28.42-300x51.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure>\n\n\n\n<p>\u57fa\u76e4\uff1a\u6d41\u77f3\u306b\u901f\u3044\u3067\u3059\u306d\u3002\u3068\u306f\u3044\u3048\u3001CRC32\u306e\u534a\u5206\u7a0b\u5ea6\u306f\u98df\u3046\u3068\u2026<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u591a\u6570\u306e\u7d30\u304b\u3044\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u3080\u3068\u3053\u308d\u3067\u5f8b\u901f\u3055\u308c\u3066\u3044\u307e\u3059\u304c\u3001\u3067\u3063\u304b\u3044\u30d5\u30a1\u30a4\u30eb\u306esum\u306a\u3089\u30012GB\/s \u4ee5\u4e0a\u51fa\u307e\u3059\u3002\u3082\u3061\u308d\u3093\u3001\u30d5\u30a1\u30a4\u30eb\u304c\u30e1\u30e2\u30ea\u4e0a\u306b\u30d0\u30c3\u30d5\u30a1\u3055\u308c\u3066\u305f\u5834\u5408\u3067\u3059\u304c\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u305d\u3057\u3066\u6700\u5f8c\u306b\u3001\u4e2d\u8eab\u3092\u8aad\u307e\u306a\u3044\u3067\u5916\u5074\u3060\u3051\u306a\u3081\u308b\u5f0f\u3002\u3053\u3053\u3067\u306f\u30b5\u30a4\u30ba\u306e\u548c\u3060\u3051\u8a08\u7b97\u3057\u3066\u3044\u307e\u3059\u3002\u5404\u30d5\u30a1\u30a4\u30eb\u306e\u65e5\u4ed8\u3068\u30b5\u30a4\u30ba\u306e\u5217\u3092CRC\u306b\u3067\u3082\u3059\u308c\u3070\u3001\u5909\u66f4\u306e\u691c\u51fa\u306b\u306f\u5341\u5206\u304b\u3082\u77e5\u308c\u307e\u305b\u3093\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"648\" height=\"110\" src=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.30.57.png\" alt=\"\" class=\"wp-image-15126\" srcset=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.30.57.png 648w, https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-20.30.57-300x51.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure>\n\n\n\n<p>\u57fa\u76e4\uff1aSSD\u306a\u3089\u307e\u3060\u8ffd\u968f\u3059\u308b\u304b\u3082\u77e5\u308c\u307e\u305b\u3093\u306d\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1a\u7d50\u8ad6\u3068\u3057\u3066\u306f\u3001tar \u306f GShell\u7248\u306e sync \u306b\u4f7f\u3046\u306b\u306f\u9045\u3059\u304e\u308b\u3068\u3044\u3046\u3053\u3068\u3067\u3059\u306d\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u5c11\u306a\u304f\u3068\u3082\u3053\u306emacOS\u5099\u3048\u4ed8\u3051\u306etar\u3067\u306f\u3002\u30ae\u30ac\u30d3\u30c3\u30c8\u306e\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u3001100MB\/s \u306e\u30cd\u30c3\u30c8\u3092\u751f\u304b\u305b\u306a\u3044\u3067\u3059\u306d\u300220MB\/s \u306b\u5f8b\u901f\u3057\u3066\u3057\u307e\u3046\u304b\u3082\u77e5\u308c\u306a\u3044\u3002\u305d\u308c\u306b\u3069\u306e\u9053\u3001\u5927\u304d\u306a\u30d5\u30a1\u30a4\u30eb\u306e\u4e2d\u3092\u30d6\u30ed\u30c3\u30af\u5316\u3057\u3066\u5dee\u5206\u3060\u3051sync\u3059\u308b\u969b\u306b\u306f\u3001tar\u306e\u65b9\u6cd5\u306f\u4f7f\u3048\u306a\u3044\u3067\u3059\u3002<\/p>\n\n\n\n<p class=\"has-text-align-center\">\uff0a\u3000\uff0a\u3000\uff0a<\/p>\n\n\n\n<p>\u793e\u9577\uff1aGShell\u7248\u306esync\u30b3\u30de\u30f3\u30c9\u306f jsync \u3068\u304b\u306b\u306a\u308b\u3093\u3067\u3059\u304b\uff1f<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u3044\u3048\u3082\u3046\u3044\u3061\u3044\u3061\u30c8\u30c3\u30d7\u30ec\u30d9\u30eb\b\u306e\u30b3\u30de\u30f3\u30c9\u540d\u3092\u4ed8\u3051\u308b\u306e\u306f\u9762\u5012\u306a\u306e\u3067\u3001x sync \u3068\u304b x put \u3068\u304b\u306b\u3057\u3088\u3046\u3068\u601d\u3044\u307e\u3059\u3002OpenSSL\u5f0f\u3067\u3059\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1aj \u3058\u3083\u306a\u304f\u3066 x \u306a\u3093\u3067\u3059\u304b\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1aj \u3088\u308a x \u306e\u307b\u3046\u304c\u30ab\u30c3\u30b3\u3044\u3044\u304b\u306a\u307f\u305f\u3044\u306a\u3002j \u306e\u5f31\u70b9\u306f\u3001\u7279\u306b\u5c0f\u6587\u5b57\u3067\u306f\u898b\u6804\u3048\u304c\u60aa\u3044\u3068\u3044\u3046\u304b\u3001i\u3068\u5224\u5225\u304c\u3057\u306b\u304f\u3044\u3053\u3068\u3067\u3059\u3002<\/p>\n\n\n\n<p>\u57fa\u76e4\uff1a\u30d5\u30a9\u30f3\u30c8\u306b\u3082\u3088\u308a\u307e\u3059\u304c\u3001\u5927\u6587\u5b57 X \u3068\u5c0f\u6587\u5b57 x \u304c\u5358\u4f53\u3067\u306f\u533a\u5225\u3057\u306b\u304f\u3044\u3068\u3044\u3046\u554f\u984c\u304c\u3042\u308b\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1a\u500b\u4eba\u7684\u306b\u306f y \u304c\u3044\u3044\u3067\u3059\u306d\u3002y \u3068 Y \u306f\u3075\u3064\u3046\u660e\u3089\u304b\u306b\u9055\u3046\u3002\u3060\u3082\u3093\u3067\u308f\u305f\u3057\u306fDeleGate\u7248\u306e\u30ea\u30e2\u30fc\u30c8\u30b7\u30a7\u30eb\u3092yysh\u306b\u3057\u307e\u3057\u305f\u3002b \u3068 B \u3067\u3082\u826f\u3044\u3067\u3059\u304c\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1ar \u3068 R \u3068\u3044\u3046\u7dda\u3082\u3042\u308b\u3068\u601d\u3044\u307e\u3059\u304c\u3001r \u306e\u30d5\u30a9\u30f3\u30c8\u304c\u4e00\u822c\u306b\u3057\u3087\u307c\u3044\u3067\u3059\u306d\u3002\bq \u3082 p \u3082 t \u3082\u3057\u3087\u307c\u3044\u3002l \u306f 1\u3068\u533a\u5225\u304c\u3064\u304b\u306a\u3044\u3053\u3068\u304c\u591a\u3044\u3002k \u306f\u30c8\u30dd\u30ed\u30b8\u30fc\u7684\u306b\u306f K \u3068\u540c\u3058\u2026\u3000\u305d\u3046\u3044\u3046\u89b3\u70b9\u304b\u3089\u306f\u3001y \u3068 Y \u3082\u843d\u7b2c\u3067\u306f\u3042\u308a\u307e\u3059\u304c\u3002\u5019\u88dc\u306f\u3001\b\ba\/A\u3001b\/B\u3001d\/D\u3001e\/E\u3001f\/F\u3001g\/G\u3068\u3001\uff48\/H\u3001i\/I\u3001j\/J\u3001n\/N\u3001q\/Q\u3001r\/R\u3001t\/T\u3001y\/Y \u3042\u305f\u308a\u3067\u3059\u304b\u306d\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1a\u6bcd\u97f3\u5b57\u306fIME\u3068\u5e72\u6e09\u3059\u308b\u53ef\u80fd\u6027\u304c\u3042\u3063\u3066\u3044\u3084\u3067\u3059\u3051\u3069\u3001e \u3068\u3044\u3046\u5c0f\u6587\u5b57\u306f\u597d\u304d\u3067\u3059\u3002g \u306f\u30ab\u30c3\u30b3\u3044\u3044\u3051\u3069\u3001\u4e0b\u306b\u306f\u307f\u51fa\u3066\u308b\u306e\u304c\u3061\u3087\u3063\u3068\u5acc\u3002b \u3068 d\u3068\u304b\u3001h \u3068 n \u3068\u304b\u3001 q \u3068 p \u3068\u304b\u3001t \u3068 f \u3068\u304b\u3001\u4f3c\u305f\u5f62\u72b6\u306e\u304c\u3042\u308b\u306e\u3082\u5acc\u3002<\/p>\n\n\n\n<p>\u57fa\u76e4\uff1a\u5019\u88dc\u304c a\/A \u3068 e\/E \u306b\u7d5e\u3089\u308c\u307e\u3057\u305f\uff57<\/p>\n\n\n\n<p>\u793e\u9577\uff1ae\u306f\u5927\u6587\u5b57\u306eE\u306e\u5f62\u72b6\u304c\u304c\u3055\u3064\u306a\u306e\u304c\u5acc\u3002F\u306b\u4f3c\u3066\u308b\u3057\u3002a \u306b\u3057\u307e\u3057\u3087\u3046\u3002<\/p>\n\n\n\n<p>\u57fa\u76e4\uff1a\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8\u4e2d\u306e\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8\u3067\u3059\u306d\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1a\u3067\u306f a \u306b\u3057\u307e\u3057\u3087\u3046\u3002\u5f53\u793e\u3068\u3057\u3066\u306e\u6b63\u5f0f\u6c7a\u5b9a\u3067\u3059\u3002GShell\u3092\u3084\u3081\u3066AlphaShell \u306b\u6539\u540d\u3059\u308b\u3068\u826f\u3044\u304b\u3082\u3067\u3059\u306d\u3002\u7565\u8a18\u304a\u3088\u3073\u30b3\u30de\u30f3\u30c9\u540d\u306f ash\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u6c38\u9060\u306e\u30a2\u30eb\u30d5\u30a1\u7248\u3067\u3042\u308b\u3068\u3002\u3042\u3001\u30d5\u30a9\u30f3\u30c8\u306b\u3088\u3063\u3066\u03b1\u306f\u3044\u307e\u3044\u3061\u898b\u6804\u3048\u3057\u306a\u3044\u3068\u3044\u3046\u5f31\u70b9\u304c\u2026\u3000\u03b2\u306e\u307b\u3046\u304c\u30ab\u30c3\u30b3\u3044\u3044\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u30d3\u30eb\u30c8\u30a4\u30f3\u30b3\u30de\u30f3\u30c9\u306e\u6b63\u5f0f\u540d\u79f0\u3082 alpha \u30b3\u30de\u30f3\u30c9\u3067\u3059\u304b\u306d\u3002\u3042\u3001\u305d\u3046\u3059\u308b\u3068 a sync \u306f async \u3092\u6697\u793a\u3057\u3066\u3044\u308b\u307f\u305f\u3044\u3067\u9762\u767d\u3044\u3067\u3059\u306d\uff57<\/p>\n\n\n\n<p>\u57fa\u76e4\uff1a\u306a\u3093\u306b\u3057\u308d\u5185\u90e8\u30b3\u30de\u30f3\u30c9\u306f1\u6587\u5b57\u3068\u3044\u3046\u306e\u306f\u6c17\u5206\u304c\u826f\u3044\u3067\u3059\u3002\u591a\u5206\u305d\u3093\u306a\u5916\u90e8\u30b3\u30de\u30f3\u30c9\u306f\u7121\u3044\u3067\u3057\u3087\u3046\u2026<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"648\" height=\"459\" src=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-12.00.23.png\" alt=\"\" class=\"wp-image-15109\" srcset=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-12.00.23.png 648w, https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-12.00.23-300x213.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure>\n\n\n\n<p>\u793e\u9577\uff1a\u305d\u3046\u3044\u3048\u3070 w \u304c\u3042\u308a\u307e\u3057\u305f\u3002\u6700\u8fd1\u306f\u3042\u307e\u308a\u4f7f\u3046\u5fc5\u8981\u304c\u306a\u304f\u306a\u308a\u307e\u3057\u305f\u304c\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1azsh \u306f r \u3092\u30d3\u30eb\u30c8\u30a4\u30f3\u30b3\u30de\u30f3\u30c9\u306b\u3057\u3066\u308b\u3093\u3067\u3059\u306d\u3002\u306a\u3093\u3060\u308d\u3046\u30fb\u30fb\u30fb\u3000man zshbuiltins\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" width=\"648\" height=\"49\" src=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-12.05.22.png\" alt=\"\" class=\"wp-image-15110\" srcset=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-12.05.22.png 648w, https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/Screen-Shot-2020-08-25-at-12.05.22-300x23.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure>\n\n\n\n<p>\u57fa\u76e4\uff1a\u305d\u308c\u3001alias \u3067\u826f\u304f\u306d\uff1f<\/p>\n\n\n\n<p>\u793e\u9577\uff1aalias  \u3067\u8868\u73fe\u3067\u304d\u306a\u3044\u4e8b\u60c5\u304c\u3042\u308b\u3093\u3067\u3057\u3087\u3046\u306d\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u3057\u304b\u3057\u4eca\u3069\u304d\u3001\u30cf\u30a4\u30d1\u30fc\u30c6\u30ad\u30b9\u30c8\u3067\u306a\u3044\u30de\u30cb\u30e5\u30a2\u30eb\u3068\u304b\u3001\u3064\u3089\u3059\u304e\u307e\u3059\u306d\u3002GShell\u3067\u306f\u304d\u3063\u3061\u308a\u3001HTML\/HTTP\u3067\u30d3\u30eb\u30c8\u30a4\u30f3\u30de\u30cb\u30e5\u30a2\u30eb\u3092\u30b5\u30fc\u30d3\u30b9\u3057\u305f\u3044\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p class=\"has-text-align-center\">\uff0a\u3000\uff0a\u3000\uff0a<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u4eca\u65e5\u306fTCP\u3092\u675f\u306d\u3066\u4f7f\u3046\u65b9\u6cd5\u3092\u3084\u3063\u3066\u307f\u3088\u3046\u3068\u601d\u3063\u305f\u306e\u3067\u3059\u304c\u3001\u30c1\u30a7\u30c3\u30af\u30b5\u30e0\u306b\u30cf\u30de\u3063\u3066\u3057\u307e\u3044\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<p>\u793e\u9577\uff1a\u3067\u3082CRC\u306f\u610f\u5916\u3068\u901f\u3044\u3068\u3044\u3046\u304b\u3002\u307e\u3042\u5b9f\u969b\u30c7\u30a3\u30b9\u30af\u30a2\u30af\u30bb\u30b9\u306b\u4f7f\u308f\u308c\u3066\u308b\u3093\u3060\u304b\u3089\u5f53\u305f\u308a\u524d\u3067\u3057\u3087\u3046\u3051\u3069\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1a\u30cf\u30fc\u30c9\u3067\u5b9f\u88c5\u3059\u308c\u3070\u3001\u30e1\u30e2\u30ea\u8ee2\u9001\u3068\u540c\u7b49\u306e\u901f\u5ea6\u3067\u30a4\u30b1\u308b\u3067\u3057\u3087\u3046\u306d\u3002\u3066\u3044\u3046\u304b\u3001\u5b9f\u969b\u305d\u3046\u306a\u3063\u3066\u308b\u3093\u3060\u3068\u601d\u3044\u307e\u3059\u304c\u3002\u7d44\u307f\u8fbc\u307f\u306e\u30c1\u30c3\u30d7\u306b\u306fCRC\u30e6\u30cb\u30c3\u30c8\u304c\u3075\u3064\u3046\u306b\u4ed8\u3044\u3066\u307e\u3059\u304b\u3089\u3001\u30a4\u30f3\u30c6\u30eb\u306e\u30c1\u30c3\u30d7\u306b\u3082\u5f53\u7136\u5185\u8535\u3057\u3066\u3044\u308b\u3068\u601d\u3046\u3093\u3067\u3059\u3002\u305d\u308c\u3092\u30e6\u30fc\u30b6\u306b\u958b\u653e\u3057\u3066\u3044\u308b\u304b\u3067\u3059\u306d\u3002<\/p>\n\n\n\n<p>\u793e\u982d\uff1aCRC\u4ed8\u304d\u306eDMA\u3092\u30e6\u30fc\u30b6\u304c\u4f7f\u3048\u308b\u3068\u826f\u3044\u3067\u3059\u306d\u3002\u3068\u3044\u3046\u304b\u3001Go\u306eRead\u3042\u305f\u308a\u3068\u304b\u3001\u305d\u3082\u305d\u3082OS\u306eread\/write, send\/recv \u30b7\u30b9\u30c6\u30e0\u30b3\u30fc\u30eb\u306b\u305d\u3046\u3044\u3046\u30d5\u30e9\u30b0\u304c\u3042\u308c\u3070\u30e6\u30fc\u30b6\u304c\u3044\u3061\u3044\u3061\u304b\u66f8\u304b\u306a\u304f\u3066\u826f\u3044\u3068\u601d\u3044\u307e\u3059\u304c\u3002\u5358\u306a\u308b\u30aa\u30af\u30c6\u30c3\u30c8\u30b9\u30c8\u30ea\u30fc\u30e0\u306e\u6c4e\u7528CRC\u3002<\/p>\n\n\n\n<p>\u958b\u767a\uff1aioctl \u3068\u304b\u306b\u3042\u308a\u307e\u3059\u304b\u306d\uff1f<\/p>\n\n\n\n<p>-- 2020-0825 SatoxITS<\/p>\n\n\n\n<ul><li>\u30e1\u30e2<ol><li>NNTP\u306b\u304a\u3051\u308bIHAVE\/SENDME\u7684\u30d7\u30ed\u30c8\u30b3\u30eb\u3002\u53cc\u65b9\u5411\u306bIHAVE\u3002DOYOUHAVE<\/li><li>\u5e38\u6642\u81ea\u5206\u306e\u5168\u30d5\u30a1\u30a4\u30eb\u306e\u30cf\u30c3\u30b7\u30e5\u3092\u7dad\u6301\u3057\u3066\u7f6e\u304f\u3002\u30d5\u30a1\u30a4\u30eb\u5909\u66f4\u76e3\u8996\u3002inode\u30c6\u30fc\u30d6\u30eb\u76e3\u8996<\/li><li>OOB\u306fSSL\u30e9\u30a4\u30d6\u30e9\u30ea\u7d4c\u7531\u3067\u306f\u4f7f\u3048\u306a\u3044<\/li><li>TCP\u30922\u672c\u4ee5\u4e0a\u675f\u306d\u3066\u4f7f\u3046\u3002\u7dca\u6025\u30c1\u30e3\u30cd\u30eb\u3068\u30d0\u30c3\u30af\u30b0\u30e9\u30a6\u30f3\u30c9\u7684\u30c1\u30e3\u30cd\u30eb\u3002\u7121\u9650\u9577\u30c7\u30fc\u30bf\u30b9\u30c8\u30ea\u30fc\u30e0\u30c1\u30e3\u30cd\u30eb<\/li><\/ol><\/li><\/ul>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/GShell-0.2.1-\u2212-\u30c4\u30a4\u30b9\u30c6\u30c3\u30c8\u3099\u30b9\u30c8\u30ea\u30fc\u30e0-\u2013-\u682a\u5f0f\u4f1a\u793e-ITS-more.pdf\">GShell-0.2.1-\u2212-\u30c4\u30a4\u30b9\u30c6\u30c3\u30c8\u3099\u30b9\u30c8\u30ea\u30fc\u30e0-\u2013-\u682a\u5f0f\u4f1a\u793e-ITS-more<\/a><a href=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/GShell-0.2.1-\u2212-\u30c4\u30a4\u30b9\u30c6\u30c3\u30c8\u3099\u30b9\u30c8\u30ea\u30fc\u30e0-\u2013-\u682a\u5f0f\u4f1a\u793e-ITS-more.pdf\" class=\"wp-block-file__button\" download>\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9<\/a><\/div>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/http-im3-gsh-gsh-0.2.1.go_.pdf\">http-im3-gsh-gsh-0.2.1.go_<\/a><a href=\"https:\/\/its-more.jp\/ja_jp\/wp-content\/uploads\/2020\/08\/http-im3-gsh-gsh-0.2.1.go_.pdf\" class=\"wp-block-file__button\" download>\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9<\/a><\/div>\n\n\n\n\/*<html>\n<span id=\"gsh\">\n<link rel=\"icon\" href=\"GShell-Logo05icon.png\">\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>GShell-0.2.1 by SatoxITS<\/title>\n<header id=\"banner\" height=\"100px\" onclick=\"shiftBG();\" style=\"\">\n<div align=\"right\"><note>GShell version 0.2.1 \/\/ 2020-08-25 \/\/ SatoxITS<\/note><\/div>\n<\/header>\n<h2>GShell \/\/ a General purpose Shell built on the top of Golang<\/h2>\n<p>\n<note>\nIt is a shell for myself, by myself, of myself. --SatoxITS(^-^)\n<\/note>\n<\/p>\n<span id=\"gsh-menu\">\n| <span onclick=\"html_new();\">NewWindow<\/span>\n| <span onclick=\"html_open();\">Unfold<\/span>\n| <span onclick=\"html_fold();\">Fold<\/span>\n| <span onclick=\"html_stop();\">Stop<\/span>\n| <span onclick=\"html_close();\">Close<\/span>\n|<\/span>\n*\/\n\/*\n<details id=\"html-src\" onclick=\"frame_open();\"><summary>Total Source of GShell<\/summary><div>\n<h2>The full of this HTML including the Go code is here.<\/h2>\n<span id=\"src-frame\"><\/span> \/\/ a window to show source code\n<\/div><\/details>\n*\/\n\/*\n<details id=\"overview\"><summary>Overview<\/summary><div class=\"gsh-src\">\nTo be written\n<\/div>\n<\/details>\n*\/\n\/*\n<details id=\"index\">\n<summary>Go Source Code Index<\/summary><div class=\"gsh-src\" onclick=\"document.getElementById('gsh-gocode').open=true;\">\nImplementation\n\tStructures\n\t\t<a href=\"#import\">import<\/a>\n\t\t<a href=\"#struct\">struct<\/a>\n\tMain functions\n\t\t<a href=\"#comexpansion\">str-expansion<\/a>\t\/\/ macro processor\n\t\t<a href=\"#finder\">finder<\/a>\t\t\/\/ builtin find + du\n\t\t<a href=\"#grep\">grep<\/a>\t\t\/\/ builtin grep + wc + cksum + ...\n\t\t<a href=\"#plugin\">plugin<\/a>\t\t\/\/ plugin commands\n\t\t<a href=\"#ex-commands\">system<\/a>\t\t\/\/ external commands\n\t\t<a href=\"#builtin\">builtin<\/a>\t\t\/\/ builtin commands\n\t\t<a href=\"#network\">network<\/a>\t\t\/\/ socket handler\n\t\t<a href=\"#remote-sh\">remote-sh<\/a>\t\/\/ remote shell\n\t\t<a href=\"#redirect\">redirect<\/a>\t\/\/ StdIn\/Out redireciton\n\t\t<a href=\"#history\">history<\/a>\t\t\/\/ command history\n\t\t<a href=\"#rusage\">rusage<\/a>\t\t\/\/ resouce usage\n\t\t<a href=\"#encode\">encode<\/a>\t\t\/\/ encode \/ decode\n\t\t<a href=\"#IME\">IME<\/a>\t\t\/\/ command line IME\n\t\t<a href=\"#getline\">getline<\/a>\t\t\/\/ line editor\n\t\t<a href=\"#scanf\">scanf<\/a>\t\t\/\/ string decomposer\n\t\t<a href=\"#interpreter\">interpreter<\/a>\t\/\/ command interpreter\n\t\t<a href=\"#main\">main<\/a>\n<\/div>\n<\/details>\n*\/\n\/\/<details id=\"gsh-gocode\">\n\/\/<summary>Go Source Code<\/summary><div class=\"gsh-src\" onclick=\"document.getElementById('gsh-gocode').open=false;\">\n\/\/ gsh - Go lang based Shell\n\/\/ (c) 2020 ITS more Co., Ltd.\n\/\/ 2020-0807 created by SatoxITS (sato@its-more.jp)\n\npackage main \/\/ gsh main\n\/\/ <a name=\"import\">Imported packages<\/a> \/\/ <a href=\"https:\/\/golang.org\/pkg\/\">Packages<\/a>\nimport (\n\t\"fmt\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/fmt\/\">fmt<\/a>\n\t\"strings\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/strings\/\">strings<\/a>\n\t\"strconv\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/strconv\/\">strconv<\/a>\n\t\"sort\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/sort\/\">sort<\/a>\n\t\"time\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/time\/\">time<\/a>\n\t\"bufio\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/bufio\/\">bufio<\/a>\n\t\"io\/ioutil\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/io\/ioutil\/\">ioutil<\/a>\n\t\"os\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/os\/\">os<\/a>\n\t\"syscall\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/syscall\/\">syscall<\/a>\n\t\"plugin\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/plugin\/\">plugin<\/a>\n\t\"net\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/net\/\">net<\/a>\n\t\"net\/http\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/net\/http\/\">http<\/a>\n\t\/\/\"html\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/html\/\">html<\/a>\n\t\"path\/filepath\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/path\/filepath\/\">filepath<\/a>\n\t\"go\/types\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/go\/types\/\">types<\/a>\n\t\"go\/token\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/go\/token\/\">token<\/a>\n\t\"encoding\/base64\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/encoding\/base64\/\">base64<\/a>\n\t\"unicode\/utf8\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/unicode\/utf8\/\">utf8<\/a>\n\t\/\/\"gshdata\"\t\/\/ gshell's logo and source code\n\t\"hash\/crc32\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/unicode\/hash\/crc32\/\">crc32<\/a>\n)\n\nvar NAME = \"gsh\"\nvar AUTHOR = \"SatoxITS(^-^)\/\"\nvar VERSION = \"0.2.1\"\nvar DATE = \"2020-08-25\"\nvar LINESIZE = (8*1024)\nvar PATHSEP = \":\"\t\/\/ should be \";\" in Windows\nvar DIRSEP = \"\/\"\t\/\/ canbe \\ in Windows\nvar GSH_HOME = \".gsh\"\t\/\/ under home directory\nvar MaxStreamSize = int64(128*1024*1024*1024) \/\/ 128GiB is too large?\nvar PROMPT = \"> \"\nvar GSH_PORT = 9999\n\n\/\/ -xX logging control\n\/\/ --A-- all\n\/\/ --I-- info.\n\/\/ --D-- debug\n\/\/ --T-- time and resource usage\n\/\/ --W-- warning\n\/\/ --E-- error\n\/\/ --F-- fatal error\n\/\/ --Xn- network\n\n\/\/ <a name=\"struct\">Structures<\/a>\ntype GCommandHistory struct {\n\tStartAt\t\ttime.Time \/\/ command line execution started at\n\tEndAt\t\ttime.Time \/\/ command line execution ended at\n\tResCode\t\tint       \/\/ exit code of (external command)\n\tCmdError\terror     \/\/ error string\n\tOutData\t\t*os.File  \/\/ output of the command\n\tFoundFile\t[]string  \/\/ output - result of ufind\n\tRusagev\t\t[2]syscall.Rusage \/\/ Resource consumption, CPU time or so\n\tCmdId\t\tint       \/\/ maybe with identified with arguments or impact\n\t\t\t          \/\/ redireciton commands should not be the CmdId\n\tWorkDir\t\tstring    \/\/ working directory at start\n\tWorkDirX\tint       \/\/ index in ChdirHistory\n\tCmdLine\t\tstring    \/\/ command line\n}\ntype GChdirHistory struct {\n\tDir\t\tstring\n\tMovedAt\t\ttime.Time\n\tCmdIndex\tint\n}\ntype CmdMode struct {\n\tBackGround\tbool\n}\ntype PluginInfo struct {\n\tSpec\t\t*plugin.Plugin\n\tAddr\t\tplugin.Symbol\n\tName\t\tstring \/\/ maybe relative\n\tPath\t\tstring \/\/ this is in Plugin but hidden\n}\ntype GServer struct {\n\thost\t\tstring\n\tport\t\tstring\n}\n\n\/\/ <a href=\"https:\/\/tools.ietf.org\/html\/rfc3230\">Digest<\/a>\nconst ( \/\/ SumType\n\tSUM_ITEMS\t= 0x000001 \/\/ items count\n\tSUM_SIZE\t= 0x000002 \/\/ data length (simplly added)\n\tSUM_SIZEHASH\t= 0x000004 \/\/ data length (hashed sequence)\n\tSUM_DATEHASH\t= 0x000008 \/\/ date of data (hashed sequence)\n\t\/\/ also envelope attributes like time stamp can be a part of digest\n\t\/\/ hashed value of sizes or mod-date of files will be useful to detect changes\n\n\tSUM_WORDS\t= 0x000010 \/\/ word count is a kind of digest\n\tSUM_LINES\t= 0x000020 \/\/ line count is a kind of digest\n\tSUM_SUM64\t= 0x000040 \/\/ simple add of bytes, useful for human too\n\n\tSUM_SUM32_BITS\t= 0x000100 \/\/ the number of true bits\n\tSUM_SUM32_2BYTE = 0x000200 \/\/ 16bits words\n\tSUM_SUM32_4BYTE = 0x000400 \/\/ 32bits words\n\tSUM_SUM32_8BYTE = 0x000800 \/\/ 64bits words\n\n\tSUM_SUM16_BSD\t= 0x001000 \/\/ UNIXsum -sum -bsd\n\tSUM_SUM16_SYSV\t= 0x002000 \/\/ UNIXsum -sum -sysv\n\tSUM_UNIXFILE\t= 0x004000\n\tSUM_CRCIEEE\t= 0x008000\n)\ntype CheckSum struct {\n\tFiles\t\tint64\t\/\/ the number of files (or data)\n\tSize\t\tint64\t\/\/ content size\n\tWords\t\tint64\t\/\/ word count\n\tLines\t\tint64\t\/\/ line count\n\tSumType\t\tint\n\tSum64\t\tuint64\n\tCrc32Table\tcrc32.Table\n\tCrc32Val\tuint32\n\tSum16\t\tint\n\tCtime\t\ttime.Time\n\tAtime\t\ttime.Time\n\tMtime\t\ttime.Time\n\tStart\t\ttime.Time\n\tDone\t\ttime.Time\n\tRusgAtStart\t[2]syscall.Rusage\n\tRusgAtEnd\t[2]syscall.Rusage\n}\ntype ValueStack [][]string\ntype GshContext struct {\n\tStartDir\tstring\t\/\/ the current directory at the start\n\tGetLine\t\tstring\t\/\/ gsh-getline command as a input line editor\n\tChdirHistory\t[]GChdirHistory \/\/ the 1st entry is wd at the start\n\tgshPA\t\tsyscall.ProcAttr\n\tCommandHistory\t[]GCommandHistory\n\tCmdCurrent\tGCommandHistory\n\tBackGround\tbool\n\tBackGroundJobs\t[]int\n\tLastRusage\tsyscall.Rusage\n\tGshHomeDir\tstring\n\tTerminalId\tint\n\tCmdTrace\tbool \/\/ should be [map]\n\tCmdTime\t\tbool \/\/ should be [map]\n\tPluginFuncs\t[]PluginInfo\n\tiValues\t\t[]string\n\tiDelimiter\tstring \/\/ field sepearater of print out\n\tiFormat\t\tstring \/\/ default print format (of integer)\n\tiValStack\tValueStack\n\tLastServer\tGServer\n\tRSERV\t\tstring \/\/ [gsh:\/\/]host[:port]\n\tRWD\t\tstring \/\/ remote (target, there) working directory\n\tlastCheckSum\tCheckSum\n}\n\nfunc nsleep(ns time.Duration){\n\ttime.Sleep(ns)\n}\nfunc usleep(ns time.Duration){\n\tnsleep(ns*1000)\n}\nfunc msleep(ns time.Duration){\n\tnsleep(ns*1000000)\n}\nfunc sleep(ns time.Duration){\n\tnsleep(ns*1000000000)\n}\n\nfunc strBegins(str, pat string)(bool){\n\tif len(pat) <= len(str){\n\t\tyes := str[0:len(pat)] == pat\n\t\t\/\/fmt.Printf(\"--D-- strBegins(%v,%v)=%v\\n\",str,pat,yes)\n\t\treturn yes\n\t}\n\t\/\/fmt.Printf(\"--D-- strBegins(%v,%v)=%v\\n\",str,pat,false)\n\treturn false\n}\nfunc isin(what string, list []string) bool {\n\tfor _, v := range list  {\n\t\tif v == what {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc isinX(what string,list[]string)(int){\n\tfor i,v := range list {\n\t\tif v == what {\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\n\nfunc env(opts []string) {\n\tenv := os.Environ()\n\tif isin(\"-s\", opts){\n\t\tsort.Slice(env, func(i,j int) bool {\n\t\t\treturn env[i] < env[j]\n\t\t})\n\t}\n\tfor _, v := range env {\n\t\tfmt.Printf(\"%v\\n\",v)\n\t}\n}\n\n\/\/ - rewriting should be context dependent\n\/\/ - should postpone until the real point of evaluation\n\/\/ - should rewrite only known notation of symobl\nfunc scanInt(str string)(val int,leng int){\n\tleng = -1\n\tfor i,ch := range str {\n\t\tif '0' <= ch && ch <= '9' {\n\t\t\tleng = i+1\n\t\t}else{\n\t\t\tbreak\n\t\t}\n\t}\n\tif 0 < leng {\n\t\tival,_ := strconv.Atoi(str[0:leng])\n\t\treturn ival,leng\n\t}else{\n\t\treturn 0,0\n\t}\n}\nfunc substHistory(gshCtx *GshContext,str string,i int,rstr string)(leng int,rst string){\n\tif len(str[i+1:]) == 0 {\n\t\treturn 0,rstr\n\t}\n\thi := 0\n\thistlen := len(gshCtx.CommandHistory)\n\tif str[i+1] == '!' {\n\t\thi = histlen - 1\n\t\tleng = 1\n\t}else{\n\t\thi,leng = scanInt(str[i+1:])\n\t\tif leng == 0 {\n\t\t\treturn 0,rstr\n\t\t}\n\t\tif hi < 0 {\n\t\t\thi = histlen + hi\n\t\t}\n\t}\n\tif 0 <= hi && hi < histlen {\n\t\tvar ext byte\n\t\tif 1 < len(str[i+leng:]) {\n\t\t\text = str[i+leng:][1]\n\t\t}\n\t\t\/\/fmt.Printf(\"--D-- %v(%c)\\n\",str[i+leng:],str[i+leng])\n\t\tif ext == 'f' {\n\t\t\tleng += 1\n\t\t\txlist := []string{}\n\t\t\tlist := gshCtx.CommandHistory[hi].FoundFile\n\t\t\tfor _,v := range list {\n\t\t\t\t\/\/list[i] = escapeWhiteSP(v)\n\t\t\t\txlist = append(xlist,escapeWhiteSP(v))\n\t\t\t}\n\t\t\t\/\/rstr += strings.Join(list,\" \")\n\t\t\trstr += strings.Join(xlist,\" \")\n\t\t}else\n\t\tif ext == '@' || ext == 'd' {\n\t\t\t\/\/ !N@ .. workdir at the start of the command\n\t\t\tleng += 1\n\t\t\trstr += gshCtx.CommandHistory[hi].WorkDir\n\t\t}else{\n\t\t\trstr += gshCtx.CommandHistory[hi].CmdLine\n\t\t}\n\t}else{\n\t\tleng = 0\n\t}\n\treturn leng,rstr\n}\nfunc escapeWhiteSP(str string)(string){\n\tif len(str) == 0 {\n\t\treturn \"\\\\z\" \/\/ empty, to be ignored\n\t}\n\trstr := \"\"\n\tfor _,ch := range str {\n\t\tswitch ch {\n\t\t\tcase '\\\\': rstr += \"\\\\\\\\\"\n\t\t\tcase ' ': rstr += \"\\\\s\"\n\t\t\tcase '\\t': rstr += \"\\\\t\"\n\t\t\tcase '\\r': rstr += \"\\\\r\"\n\t\t\tcase '\\n': rstr += \"\\\\n\"\n\t\t\tdefault: rstr += string(ch)\n\t\t}\n\t}\n\treturn rstr\n}\nfunc unescapeWhiteSP(str string)(string){ \/\/ strip original escapes\n\trstr := \"\"\n\tfor i := 0; i < len(str); i++ {\n\t\tch := str[i]\n\t\tif ch == '\\\\' {\n\t\t\tif i+1 < len(str) {\n\t\t\t\tswitch str[i+1] {\n\t\t\t\t\tcase 'z':\n\t\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\trstr += string(ch)\n\t}\n\treturn rstr\n}\nfunc unescapeWhiteSPV(strv []string)([]string){ \/\/ strip original escapes\n\tustrv := []string{}\n\tfor _,v := range strv {\n\t\tustrv = append(ustrv,unescapeWhiteSP(v))\n\t}\n\treturn ustrv\n}\n\n\/\/ <a name=\"comexpansion\">str-expansion<\/a>\n\/\/ - this should be a macro processor\nfunc strsubst(gshCtx *GshContext,str string,histonly bool) string {\n\trbuff := []byte{}\n\tif false {\n\t\t\/\/@@U Unicode should be cared as a character\n\t\treturn str\n\t}\n\t\/\/rstr := \"\"\n\tinEsc := 0 \/\/ escape characer mode \n\tfor i := 0; i < len(str); i++ {\n\t\t\/\/fmt.Printf(\"--D--Subst %v:%v\\n\",i,str[i:])\n\t\tch := str[i]\n\t\tif inEsc == 0 {\n\t\t\tif ch == '!' {\n\t\t\t\t\/\/leng,xrstr := substHistory(gshCtx,str,i,rstr)\n\t\t\t\tleng,rs := substHistory(gshCtx,str,i,\"\")\n\t\t\t\tif 0 < leng {\n\t\/\/_,rs := substHistory(gshCtx,str,i,\"\")\n\trbuff = append(rbuff,[]byte(rs)...)\n\t\t\t\t\ti += leng\n\t\t\t\t\t\/\/rstr = xrstr\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tswitch ch {\n\t\t\t\tcase '\\\\': inEsc = '\\\\'; continue\n\t\t\t\t\/\/case '%':  inEsc = '%';  continue\n\t\t\t\tcase '$':\n\t\t\t}\n\t\t}\n\t\tswitch inEsc {\n\t\tcase '\\\\':\n\t\t\tswitch ch {\n\t\t\t\tcase '\\\\': ch = '\\\\'\n\t\t\t\tcase 's': ch = ' '\n\t\t\t\tcase 't': ch = '\\t'\n\t\t\t\tcase 'r': ch = '\\r'\n\t\t\t\tcase 'n': ch = '\\n'\n\t\t\t\tcase 'z': inEsc = 0; continue \/\/ empty, to be ignored\n\t\t\t}\n\t\t\tinEsc = 0 \n\t\tcase '%':\n\t\t\tswitch {\n\t\t\t\tcase ch == '%': ch = '%'\n\t\t\t\tcase ch == 'T':\n\t\t\t\t\t\/\/rstr = rstr + time.Now().Format(time.Stamp)\n\trs := time.Now().Format(time.Stamp)\n\trbuff = append(rbuff,[]byte(rs)...)\n\t\t\t\t\tinEsc = 0\n\t\t\t\t\tcontinue;\n\t\t\t\tdefault:\n\t\t\t\t\t\/\/ postpone the interpretation\n\t\t\t\t\t\/\/rstr = rstr + \"%\" + string(ch)\n\trbuff = append(rbuff,ch)\n\t\t\t\t\tinEsc = 0\n\t\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tinEsc = 0\n\t\t}\n\t\t\/\/rstr = rstr + string(ch)\n\t\trbuff = append(rbuff,ch)\n\t}\n\t\/\/fmt.Printf(\"--D--subst(%s)(%s)\\n\",str,string(rbuff))\n\treturn string(rbuff)\n\t\/\/return rstr\n}\nfunc showFileInfo(path string, opts []string) {\n\tif isin(\"-l\",opts) || isin(\"-ls\",opts) {\n\t\tfi, err := os.Stat(path)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"---------- ((%v))\",err)\n\t\t}else{\n\t\t\tmod := fi.ModTime()\n\t\t\tdate := mod.Format(time.Stamp)\n\t\t\tfmt.Printf(\"%v %8v %s \",fi.Mode(),fi.Size(),date)\n\t\t}\n\t}\n\tfmt.Printf(\"%s\",path)\n\tif isin(\"-sp\",opts) {\n\t\tfmt.Printf(\" \")\n\t}else\n\tif ! isin(\"-n\",opts) {\n\t\tfmt.Printf(\"\\n\")\n\t}\n}\nfunc userHomeDir()(string,bool){\n\t\/*\n\thomedir,_ = os.UserHomeDir() \/\/ not implemented in older Golang\n\t*\/\n\thomedir,found := os.LookupEnv(\"HOME\")\n\t\/\/fmt.Printf(\"--I-- HOME=%v(%v)\\n\",homedir,found)\n\tif !found {\n\t\treturn \"\/tmp\",found\n\t}\n\treturn homedir,found\n}\n\nfunc toFullpath(path string) (fullpath string) {\n\tif path[0] == '\/' {\n\t\treturn path\n\t}\n\tpathv := strings.Split(path,DIRSEP)\n\tswitch {\n\tcase pathv[0] == \".\":\n\t\tpathv[0], _ = os.Getwd()\n\tcase pathv[0] == \"..\": \/\/ all ones should be interpreted\n\t\tcwd, _ := os.Getwd()\n\t\tppathv := strings.Split(cwd,DIRSEP)\n\t\tpathv[0] = strings.Join(ppathv,DIRSEP)\n\tcase pathv[0] == \"~\":\n\t\tpathv[0],_ = userHomeDir()\n\tdefault:\n\t\tcwd, _ := os.Getwd()\n\t\tpathv[0] = cwd + DIRSEP + pathv[0]\n\t}\n\treturn strings.Join(pathv,DIRSEP)\n}\n\nfunc IsRegFile(path string)(bool){\n\tfi, err := os.Stat(path)\n\tif err == nil {\n\t\tfm := fi.Mode()\n\t\treturn fm.IsRegular();\n\t}\n\treturn false\n}\n\n\/\/ <a name=\"encode\">Encode \/ Decode<\/a>\n\/\/ <a href=\"https:\/\/golang.org\/pkg\/encoding\/base64\/#example_NewEncoder\">Encoder<\/a>\nfunc (gshCtx *GshContext)Enc(argv[]string){\n\tfile := os.Stdin\n\tbuff := make([]byte,LINESIZE)\n\tli := 0\n\tencoder := base64.NewEncoder(base64.StdEncoding,os.Stdout)\t\n\tfor li = 0; ; li++ {\n\t\tcount, err := file.Read(buff)\n\t\tif count <= 0 {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t\tencoder.Write(buff[0:count])\n\t}\n\tencoder.Close()\n}\nfunc (gshCtx *GshContext)Dec(argv[]string){\n\tdecoder := base64.NewDecoder(base64.StdEncoding,os.Stdin)\t\n\tli := 0\n\tbuff := make([]byte,LINESIZE)\n\tfor li = 0; ; li++ {\n\t\tcount, err := decoder.Read(buff)\n\t\tif count <= 0 {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t\tos.Stdout.Write(buff[0:count])\n\t}\n}\n\/\/ lnsp [N] [-crlf][-C \\\\]\nfunc (gshCtx *GshContext)SplitLine(argv[]string){\n\treader := bufio.NewReaderSize(os.Stdin,64*1024)\n\tni := 0\n\ttoi := 0\n\tfor ni = 0; ; ni++ {\n\t\tline, err := reader.ReadString('\\n')\n\t\tif len(line) <= 0 {\n\t\t\tif err != nil {\n\t\t\tfmt.Fprintf(os.Stderr,\"--I-- lnsp %d to %d (%v)\\n\",ni,toi,err)\n\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\toff := 0\n\t\tilen := len(line)\n\t\tremlen := len(line)\n\t\tfor oi := 0; 0 < remlen; oi++ {\n\t\t\tolen := remlen\n\t\t\taddnl := false\n\t\t\tif 72 < olen {\n\t\t\t\tolen = 72\n\t\t\t\taddnl = true\n\t\t\t}\n\t\t\tfmt.Fprintf(os.Stderr,\"--D-- write %d [%d.%d] %d %d\/%d\/%d\\n\",\n\t\t\t\ttoi,ni,oi,off,olen,remlen,ilen)\n\t\t\ttoi += 1\n\t\t\tos.Stdout.Write([]byte(line[0:olen]))\n\t\t\tif addnl {\n\t\t\t\t\/\/os.Stdout.Write([]byte(\"\\r\\n\"))\n\t\t\t\tos.Stdout.Write([]byte(\"\\\\\"))\n\t\t\t\tos.Stdout.Write([]byte(\"\\n\"))\n\t\t\t}\n\t\t\tline = line[olen:]\n\t\t\toff += olen\n\t\t\tremlen -= olen\n\t\t}\n\t}\n\tfmt.Fprintf(os.Stderr,\"--I-- lnsp %d to %d\\n\",ni,toi)\n}\n\n\/\/ CRC32 <a href=http:\/\/golang.jp\/pkg\/hash-crc32>crc32<\/a>\n\/\/ 1 0000 0100 1100 0001 0001 1101 1011 0111\nvar CRC32UNIX uint32 = uint32(0x04C11DB7) \/\/ Unix cksum\nvar CRC32IEEE uint32 = uint32(0xEDB88320)\nfunc byteCRC32add(crc uint32,str[]byte,len uint64)(uint32){ \n\tvar i uint64\n\tfor i = 0; i < len; i++ {\n\t\tvar oct = str[i]\n\t\tfor bi := 0; bi < 8; bi++ {\n\t\t\tovf1 := (crc & 0x80000000) != 0\n\t\t\tovf2 := (oct & 0x80) != 0\n\t\t\tovf := (ovf1 && !ovf2) || (!ovf1 && ovf2)\n\t\t\toct <<= 1\n\t\t\tcrc <<= 1\n\t\t\tif ovf { crc ^= CRC32UNIX }\n\t\t}\n\t}\n\treturn crc;\n}\nfunc byteCRC32end(crc uint32, len uint64)(uint32){\n\tvar slen = make([]byte,4)\n\tvar li = 0\n        for li = 0; li < 4; {\n                slen[li] = byte(len)\n\t\tli += 1\n                len >>= 8\n                if( len == 0 ){\n                        break\n\t\t}\n        }\n        crc = byteCRC32add(crc,slen,uint64(li))\n        crc ^= 0xFFFFFFFF\n        return crc\n}\nfunc byteCRC32(str[]byte,len uint64)(crc uint32){\n\tcrc = byteCRC32add(0,str,len)\n\tcrc = byteCRC32end(crc,len)\n\treturn crc\n}\nfunc CRC32Finish(crc uint32, table *crc32.Table, len uint64)(uint32){\n\tvar slen = make([]byte,4)\n\tvar li = 0\n        for li = 0; li < 4; {\n                slen[li] = byte(len & 0xFF)\n\t\tli += 1\n                len >>= 8\n                if( len == 0 ){\n                        break\n\t\t}\n        }\n\tcrc = crc32.Update(crc,table,slen)\n        crc ^= 0xFFFFFFFF\n        return crc\n}\n\nfunc (gsh*GshContext)xCksum(path string,argv[]string, sum*CheckSum)(int64){\n\tif isin(\"-type\/f\",argv) && !IsRegFile(path){\n\t\treturn 0\n\t}\n\tif isin(\"-type\/d\",argv) && IsRegFile(path){\n\t\treturn 0\n\t}\n\tfile, err := os.OpenFile(path,os.O_RDONLY,0)\n\tif err != nil {\n\t\tfmt.Printf(\"--E-- cksum %v (%v)\\n\",path,err)\n\t\treturn -1\n\t}\n\tdefer file.Close()\n\tif gsh.CmdTrace { fmt.Printf(\"--I-- cksum %v %v\\n\",path,argv) }\n\n\tbi := 0\n\tvar buff = make([]byte,32*1024)\n\tvar total int64 = 0\n\tvar initTime = time.Time{}\n\tif sum.Start == initTime {\n\t\tsum.Start = time.Now()\n\t}\n\tfor bi = 0; ; bi++ {\n\t\tcount,err := file.Read(buff)\n\t\tif count <= 0 || err != nil {\n\t\t\tbreak\n\t\t}\n\t\tif (sum.SumType & SUM_SUM64) != 0 {\n\t\t\ts := sum.Sum64\n\t\t\tfor _,c := range buff[0:count] {\n\t\t\t\ts += uint64(c)\n\t\t\t}\n\t\t\tsum.Sum64 = s\n\t\t}\n\t\tif (sum.SumType & SUM_UNIXFILE) != 0 {\n\t\t\tsum.Crc32Val = byteCRC32add(sum.Crc32Val,buff,uint64(count))\n\t\t}\n\t\tif (sum.SumType & SUM_CRCIEEE) != 0 {\n\t\t\tsum.Crc32Val = crc32.Update(sum.Crc32Val,&sum.Crc32Table,buff[0:count])\n\t\t}\n\t\t\/\/ <a href=\"https:\/\/en.wikipedia.org\/wiki\/BSD_checksum\">BSD checksum<\/a>\n\t\tif (sum.SumType & SUM_SUM16_BSD) != 0 {\n\t\t\ts := sum.Sum16\n\t\t\tfor _,c := range buff[0:count] {\n\t\t\t\ts = (s >> 1) + ((s & 1) << 15)\n\t\t\t\ts += int(c)\n\t\t\t\ts &= 0xFFFF\n\t\t\t\t\/\/fmt.Printf(\"BSDsum: %d[%d] %d\\n\",sum.Size+int64(i),i,s)\n\t\t\t}\n\t\t\tsum.Sum16 = s\n\t\t}\n\t\tif (sum.SumType & SUM_SUM16_SYSV) != 0 {\n\t\t\tfor bj := 0; bj < count; bj++ {\n\t\t\t\tsum.Sum16 += int(buff[bj])\n\t\t\t}\n\t\t}\n\t\ttotal += int64(count)\n\t}\n\tsum.Done = time.Now()\n\tsum.Files += 1\n\tsum.Size += total\n\tif !isin(\"-s\",argv) {\n\t\tfmt.Printf(\"%v \",total)\n\t}\n\treturn 0\n}\n\n\/\/ <a name=\"grep\">grep<\/a>\n\/\/ \"lines\", \"lin\" or \"lnp\" for \"(text) line processor\" or \"scanner\"\n\/\/ a*,!ab,c, ... sequentioal combination of patterns\n\/\/ what \"LINE\" is should be definable\n\/\/ generic line-by-line processing\n\/\/ grep [-v]\n\/\/ cat -n -v\n\/\/ uniq [-c]\n\/\/ tail -f\n\/\/ sed s\/x\/y\/ or awk\n\/\/ grep with line count like wc\n\/\/ rewrite contents if specified\nfunc (gsh*GshContext)xGrep(path string,rexpv[]string)(int){\n\tfile, err := os.OpenFile(path,os.O_RDONLY,0)\n\tif err != nil {\n\t\tfmt.Printf(\"--E-- grep %v (%v)\\n\",path,err)\n\t\treturn -1\n\t}\n\tdefer file.Close()\n\tif gsh.CmdTrace { fmt.Printf(\"--I-- grep %v %v\\n\",path,rexpv) }\n\t\/\/reader := bufio.NewReaderSize(file,LINESIZE)\n\treader := bufio.NewReaderSize(file,80)\n\tli := 0\n\tfound := 0\n\tfor li = 0; ; li++ {\n\t\tline, err := reader.ReadString('\\n')\n\t\tif len(line) <= 0 {\n\t\t\tbreak\n\t\t}\n\t\tif 150 < len(line) {\n\t\t\t\/\/ maybe binary\n\t\t\tbreak;\n\t\t}\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t\tif 0 <= strings.Index(string(line),rexpv[0]) {\n\t\t\tfound += 1\n\t\t\tfmt.Printf(\"%s:%d: %s\",path,li,line)\n\t\t}\n\t}\n\t\t\/\/fmt.Printf(\"total %d lines %s\\n\",li,path)\n\t\/\/if( 0 < found ){ fmt.Printf(\"((found %d lines %s))\\n\",found,path); }\n\treturn found\n}\n\n\/\/ <a name=\"finder\">Finder<\/a>\n\/\/ finding files with it name and contents\n\/\/ file names are ORed\n\/\/ show the content with %x fmt list\n\/\/ ls -R\n\/\/ tar command by adding output\ntype fileSum struct {\n\tErr\tint64\t\/\/ access error or so\n\tSize\tint64\t\/\/ content size\n\tDupSize\tint64\t\/\/ content size from hard links\n\tBlocks\tint64\t\/\/ number of blocks (of 512 bytes)\n\tDupBlocks int64\t\/\/ Blocks pointed from hard links\n\tHLinks\tint64\t\/\/ hard links\n\tWords\tint64\n\tLines\tint64\n\tFiles\tint64\n\tDirs\tint64\t\/\/ the num. of directories\n\tSymLink\tint64\n\tFlats\tint64\t\/\/ the num. of flat files\n\tMaxDepth\tint64\n\tMaxNamlen\tint64\t\/\/ max. name length\n\tnextRepo\ttime.Time\n}\nfunc showFusage(dir string,fusage *fileSum){\n\tbsume := float64(((fusage.Blocks-fusage.DupBlocks)\/2)*1024)\/1000000.0\n\t\/\/bsumdup := float64((fusage.Blocks\/2)*1024)\/1000000.0\n\n\tfmt.Printf(\"%v: %v files (%vd %vs %vh) %.6f MB (%.2f MBK)\\n\",\n\t\tdir,\n\t\tfusage.Files,\n\t\tfusage.Dirs,\n\t\tfusage.SymLink,\n\t\tfusage.HLinks,\n\t\tfloat64(fusage.Size)\/1000000.0,bsume);\n}\nconst (\n\tS_IFMT    = 0170000\n\tS_IFCHR   = 0020000\n\tS_IFDIR   = 0040000\n\tS_IFREG   = 0100000\n\tS_IFLNK   = 0120000\n\tS_IFSOCK  = 0140000\n)\nfunc cumFinfo(fsum *fileSum, path string, staterr error, fstat syscall.Stat_t, argv[]string,verb bool)(*fileSum){\n\tnow := time.Now()\n\tif time.Second <= now.Sub(fsum.nextRepo) {\n\t\tif !fsum.nextRepo.IsZero(){\n\t\t\ttstmp := now.Format(time.Stamp)\n\t\t\tshowFusage(tstmp,fsum)\n\t\t}\n\t\tfsum.nextRepo = now.Add(time.Second)\n\t}\n\tif staterr != nil {\n\t\tfsum.Err += 1\n\t\treturn fsum\n\t}\n\tfsum.Files += 1\n\tif 1 < fstat.Nlink {\n\t\t\/\/ must count only once...\n\t\t\/\/ at least ignore ones in the same directory\n\t\t\/\/if finfo.Mode().IsRegular() {\n\t\tif (fstat.Mode & S_IFMT) == S_IFREG {\n\t\t\tfsum.HLinks += 1\n\t\t\tfsum.DupBlocks += int64(fstat.Blocks)\n\t\t\t\/\/fmt.Printf(\"---Dup HardLink %v %s\\n\",fstat.Nlink,path)\n\t\t}\n\t}\n\t\/\/fsum.Size += finfo.Size()\n\tfsum.Size += fstat.Size\n\tfsum.Blocks += int64(fstat.Blocks) \n\t\/\/if verb { fmt.Printf(\"(%8dBlk) %s\",fstat.Blocks\/2,path) }\n\tif isin(\"-ls\",argv){\n\t\t\/\/if verb { fmt.Printf(\"%4d %8d \",fstat.Blksize,fstat.Blocks) }\n\/\/\t\tfmt.Printf(\"%d\\t\",fstat.Blocks\/2)\n\t}\n\t\/\/if finfo.IsDir()\n\tif (fstat.Mode & S_IFMT) == S_IFDIR {\n\t\tfsum.Dirs += 1\n\t}\n\t\/\/if (finfo.Mode() & os.ModeSymlink) != 0 \n\tif (fstat.Mode & S_IFMT) == S_IFLNK {\n\t\t\/\/if verb { fmt.Printf(\"symlink(%v,%s)\\n\",fstat.Mode,finfo.Name()) }\n\t\t\/\/{ fmt.Printf(\"symlink(%o,%s)\\n\",fstat.Mode,finfo.Name()) }\n\t\tfsum.SymLink += 1\n\t}\n\treturn fsum\n}\nfunc (gsh*GshContext)xxFindEntv(depth int,total *fileSum,dir string, dstat syscall.Stat_t, ei int, entv []string,npatv[]string,argv[]string)(*fileSum){\n\tnols := isin(\"-grep\",argv)\n\t\/\/ sort entv\n\t\/*\n\tif isin(\"-t\",argv){\n\t\tsort.Slice(filev, func(i,j int) bool {\n\t\t\treturn 0 < filev[i].ModTime().Sub(filev[j].ModTime())\n\t\t})\n\t}\n\t*\/\n\t\t\/*\n\t\tif isin(\"-u\",argv){\n\t\t\tsort.Slice(filev, func(i,j int) bool {\n\t\t\t\treturn 0 < filev[i].AccTime().Sub(filev[j].AccTime())\n\t\t\t})\n\t\t}\n\t\tif isin(\"-U\",argv){\n\t\t\tsort.Slice(filev, func(i,j int) bool {\n\t\t\t\treturn 0 < filev[i].CreatTime().Sub(filev[j].CreatTime())\n\t\t\t})\n\t\t}\n\t\t*\/\n\t\/*\n\tif isin(\"-S\",argv){\n\t\tsort.Slice(filev, func(i,j int) bool {\n\t\t\treturn filev[j].Size() < filev[i].Size()\n\t\t})\n\t}\n\t*\/\n\tfor _,filename := range entv {\n\t\tfor _,npat := range npatv {\n\t\t\tmatch := true\n\t\t\tif npat == \"*\" {\n\t\t\t\tmatch = true\n\t\t\t}else{\n\t\t\t\tmatch, _ = filepath.Match(npat,filename)\n\t\t\t}\n\t\t\tpath := dir + DIRSEP + filename\n\t\t\tif !match {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvar fstat syscall.Stat_t\n\t\t\tstaterr := syscall.Lstat(path,&fstat)\n\t\t\tif staterr != nil {\n\t\t\t\tif !isin(\"-w\",argv){fmt.Printf(\"ufind: %v\\n\",staterr) }\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif isin(\"-du\",argv) && (fstat.Mode & S_IFMT) == S_IFDIR {\n\t\t\t\t\/\/ should not show size of directory in \"-du\" mode ...\n\t\t\t}else\n\t\t\tif !nols && !isin(\"-s\",argv) && (!isin(\"-du\",argv) || isin(\"-a\",argv)) {\n\t\t\t\tif isin(\"-du\",argv) {\n\t\t\t\t\tfmt.Printf(\"%d\\t\",fstat.Blocks\/2)\n\t\t\t\t}\n\t\t\t\tshowFileInfo(path,argv)\n\t\t\t}\n\t\t\tif true { \/\/ && isin(\"-du\",argv)\n\t\t\t\ttotal = cumFinfo(total,path,staterr,fstat,argv,false)\n\t\t\t}\n\t\t\t\/*\n\t\t\tif isin(\"-wc\",argv) {\n\t\t\t}\n\t\t\t*\/\n\t\t\tif gsh.lastCheckSum.SumType != 0 {\n\t\t\t\tgsh.xCksum(path,argv,&gsh.lastCheckSum);\n\t\t\t}\n\t\t\tx := isinX(\"-grep\",argv); \/\/ -grep will be convenient like -ls\n\t\t\tif 0 <= x && x+1 <= len(argv) { \/\/ -grep will be convenient like -ls\n\t\t\t\tif IsRegFile(path){\n\t\t\t\t\tfound := gsh.xGrep(path,argv[x+1:])\n\t\t\t\t\tif 0 < found {\n\t\t\t\t\t\tfoundv := gsh.CmdCurrent.FoundFile\n\t\t\t\t\t\tif len(foundv) < 10 {\n\t\t\t\t\t\t\tgsh.CmdCurrent.FoundFile =\n\t\t\t\t\t\t\tappend(gsh.CmdCurrent.FoundFile,path)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !isin(\"-r0\",argv) { \/\/ -d 0 in du, -depth n in find\n\t\t\t\t\/\/total.Depth += 1\n\t\t\t\tif (fstat.Mode & S_IFMT) == S_IFLNK {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif dstat.Rdev != fstat.Rdev {\n\t\t\t\t\tfmt.Printf(\"--I-- don't follow differnet device %v(%v) %v(%v)\\n\",\n\t\t\t\t\t\tdir,dstat.Rdev,path,fstat.Rdev)\n\t\t\t\t}\n\t\t\t\tif (fstat.Mode & S_IFMT) == S_IFDIR {\n\t\t\t\t\ttotal = gsh.xxFind(depth+1,total,path,npatv,argv)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn total\n}\nfunc (gsh*GshContext)xxFind(depth int,total *fileSum,dir string,npatv[]string,argv[]string)(*fileSum){\n\tnols := isin(\"-grep\",argv)\n\tdirfile,oerr := os.OpenFile(dir,os.O_RDONLY,0)\n\tif oerr == nil {\n\t\t\/\/fmt.Printf(\"--I-- %v(%v)[%d]\\n\",dir,dirfile,dirfile.Fd())\n\t\tdefer dirfile.Close()\n\t}else{\n\t}\n\n\tprev := *total\n\tvar dstat syscall.Stat_t\n\tstaterr := syscall.Lstat(dir,&dstat) \/\/ should be flstat\n\n\tif staterr != nil {\n\t\tif !isin(\"-w\",argv){ fmt.Printf(\"ufind: %v\\n\",staterr) }\n\t\treturn total\n\t}\n\t\t\/\/filev,err := ioutil.ReadDir(dir)\n\t\t\/\/_,err := ioutil.ReadDir(dir) \/\/ ReadDir() heavy and bad for huge directory\n\t\t\/*\n\t\tif err != nil {\n\t\t\tif !isin(\"-w\",argv){ fmt.Printf(\"ufind: %v\\n\",err) }\n\t\t\treturn total\n\t\t}\n\t\t*\/\n\tif depth == 0 {\n\t\ttotal = cumFinfo(total,dir,staterr,dstat,argv,true)\n\t\tif !nols && !isin(\"-s\",argv) && (!isin(\"-du\",argv) || isin(\"-a\",argv)) {\n\t\t\tshowFileInfo(dir,argv)\n\t\t}\n\t}\n\t\/\/ it it is not a directory, just scan it and finish\n\n\tfor ei := 0; ; ei++ {\n\t\tentv,rderr := dirfile.Readdirnames(8*1024)\n\t\tif len(entv) == 0 || rderr != nil {\n\t\t\t\/\/if rderr != nil { fmt.Printf(\"[%d] len=%d (%v)\\n\",ei,len(entv),rderr) }\n\t\t\tbreak\n\t\t}\n\t\tif 0 < ei {\n\t\t\tfmt.Printf(\"--I-- xxFind[%d] %d large-dir: %s\\n\",ei,len(entv),dir)\n\t\t}\n\t\ttotal = gsh.xxFindEntv(depth,total,dir,dstat,ei,entv,npatv,argv)\n\t}\n\tif isin(\"-du\",argv) {\n\t\t\/\/ if in \"du\" mode\n\t\tfmt.Printf(\"%d\\t%s\\n\",(total.Blocks-prev.Blocks)\/2,dir)\n\t}\n\treturn total\n}\n\n\/\/ {ufind|fu|ls} [Files] [\/\/ Names] [-- Expressions]\n\/\/  Files is \".\" by default\n\/\/  Names is \"*\" by default\n\/\/  Expressions is \"-print\" by default for \"ufind\", or -du for \"fu\" command\nfunc (gsh*GshContext)xFind(argv[]string){\n\tif 0 < len(argv) && strBegins(argv[0],\"?\"){\n\t\tshowFound(gsh,argv)\n\t\treturn\n\t}\n\tif isin(\"-cksum\",argv) || isin(\"-sum\",argv) {\n\t\tgsh.lastCheckSum = CheckSum{}\n\t\tif isin(\"-sum\",argv) && isin(\"-add\",argv) {\n\t\t\tgsh.lastCheckSum.SumType |= SUM_SUM64\n\t\t}else\n\t\tif isin(\"-sum\",argv) && isin(\"-size\",argv) {\n\t\t\tgsh.lastCheckSum.SumType |= SUM_SIZE\n\t\t}else\n\t\tif isin(\"-sum\",argv) && isin(\"-bsd\",argv) {\n\t\t\tgsh.lastCheckSum.SumType |= SUM_SUM16_BSD\n\t\t}else\n\t\tif isin(\"-sum\",argv) && isin(\"-sysv\",argv) {\n\t\t\tgsh.lastCheckSum.SumType |= SUM_SUM16_SYSV\n\t\t}else\n\t\tif isin(\"-sum\",argv) {\n\t\t\tgsh.lastCheckSum.SumType |= SUM_SUM64\n\t\t}\n\t\tif isin(\"-unix\",argv) {\n\t\t\tgsh.lastCheckSum.SumType |= SUM_UNIXFILE\n\t\t\tgsh.lastCheckSum.Crc32Table = *crc32.MakeTable(CRC32UNIX)\n\t\t}\n\t\tif isin(\"-ieee\",argv){\n\t\t\tgsh.lastCheckSum.SumType |= SUM_CRCIEEE\n\t\t\tgsh.lastCheckSum.Crc32Table = *crc32.MakeTable(CRC32IEEE)\n\t\t}\n\t\tgsh.lastCheckSum.RusgAtStart = Getrusagev()\n\t}\n\tvar total = fileSum{}\n\tnpats := []string{}\n\tfor _,v := range argv {\n\t\tif 0 < len(v) && v[0] != '-' {\n\t\t\tnpats = append(npats,v)\n\t\t}\n\t\tif v == \"\/\/\" { break }\n\t\tif v == \"--\" { break }\n\t\tif v == \"-grep\" { break }\n\t\tif v == \"-ls\" { break }\n\t}\n\tif len(npats) == 0 {\n\t\tnpats = []string{\"*\"}\n\t}\n\tcwd := \".\"\n\t\/\/ if to be fullpath ::: cwd, _ := os.Getwd()\n\tif len(npats) == 0 { npats = []string{\"*\"} }\n\tfusage := gsh.xxFind(0,&total,cwd,npats,argv)\n\tif gsh.lastCheckSum.SumType != 0 {\n\t\tvar sumi uint64 = 0\n\t\tsum := &gsh.lastCheckSum\n\t\tif (sum.SumType & SUM_SIZE) != 0 {\n\t\t\tsumi = uint64(sum.Size)\n\t\t}\n\t\tif (sum.SumType & SUM_SUM64) != 0 {\n\t\t\tsumi = sum.Sum64\n\t\t}\n\t\tif (sum.SumType & SUM_SUM16_SYSV) != 0 {\n\t\t\ts := uint32(sum.Sum16)\n\t\t\tr := (s & 0xFFFF) + ((s & 0xFFFFFFFF) >> 16)\n\t\t\ts = (r & 0xFFFF) + (r >> 16)\n\t\t\tsum.Crc32Val = uint32(s)\n\t\t\tsumi = uint64(s)\n\t\t}\n\t\tif (sum.SumType & SUM_SUM16_BSD) != 0 {\n\t\t\tsum.Crc32Val = uint32(sum.Sum16)\n\t\t\tsumi = uint64(sum.Sum16)\n\t\t}\n\t\tif (sum.SumType & SUM_UNIXFILE) != 0 {\n\t\t\tsum.Crc32Val = byteCRC32end(sum.Crc32Val,uint64(sum.Size))\n\t\t\tsumi = uint64(byteCRC32end(sum.Crc32Val,uint64(sum.Size)))\n\t\t}\n\t\tif 1 < sum.Files {\n\t\t\tfmt.Printf(\"%v %v \/\/ %v \/ %v files, %v\/file\\r\\n\",\n\t\t\t\tsumi,sum.Size,\n\t\t\t\tabssize(sum.Size),sum.Files,\n\t\t\t\tabssize(sum.Size\/sum.Files))\n\t\t}else{\n\t\t\tfmt.Printf(\"%v %v %v\\n\",\n\t\t\t\tsumi,sum.Size,npats[0])\n\t\t}\n\t}\n\tif !isin(\"-grep\",argv) {\n\t\tshowFusage(\"total\",fusage)\n\t}\n\tif !isin(\"-s\",argv){\n\t\thits := len(gsh.CmdCurrent.FoundFile)\n\t\tif 0 < hits {\n\t\t\tfmt.Printf(\"--I-- %d files hits \/\/ can be refered with !%df\\n\",\n\t\t\t\thits,len(gsh.CommandHistory))\n\t\t}\n\t}\n\tif gsh.lastCheckSum.SumType != 0 {\n\t\tif isin(\"-ru\",argv) {\n\t\t\tsum := &gsh.lastCheckSum\n\t\t\tsum.Done = time.Now()\n\t\t\tgsh.lastCheckSum.RusgAtEnd = Getrusagev()\n\t\t\telps := sum.Done.Sub(sum.Start)\n\t\t\tfmt.Printf(\"--cksum-size: %v (%v) \/ %v files, %v\/file\\r\\n\",\n\t\t\t\tsum.Size,abssize(sum.Size),sum.Files,abssize(sum.Size\/sum.Files))\n\t\t\tnanos := int64(elps)\n\t\t\tfmt.Printf(\"--cksum-time: %v\/total, %v\/file, %.1f files\/s, %v\\r\\n\",\n\t\t\t\tabbtime(nanos),\n\t\t\t\tabbtime(nanos\/sum.Files),\n\t\t\t\t(float64(sum.Files)*1000000000.0)\/float64(nanos),\n\t\t\t\tabbspeed(sum.Size,nanos))\n\t\t\tdiff := RusageSubv(sum.RusgAtEnd,sum.RusgAtStart)\n\t\t\tfmt.Printf(\"--cksum-rusg: %v\\n\",sRusagef(\"\",argv,diff))\n\t\t}\n\t}\n\treturn\n}\n\nfunc showFiles(files[]string){\n\tsp := \"\"\n\tfor i,file := range files {\n\t\tif 0 < i { sp = \" \" } else { sp = \"\" }\n\t\tfmt.Printf(sp+\"%s\",escapeWhiteSP(file))\n\t}\n}\nfunc showFound(gshCtx *GshContext, argv[]string){\n\tfor i,v := range gshCtx.CommandHistory {\n\t\tif 0 < len(v.FoundFile) {\n\t\t\tfmt.Printf(\"!%d (%d) \",i,len(v.FoundFile))\n\t\t\tif isin(\"-ls\",argv){\n\t\t\t\tfmt.Printf(\"\\n\")\n\t\t\t\tfor _,file := range v.FoundFile {\n\t\t\t\t\tfmt.Printf(\"\") \/\/sub number?\n\t\t\t\t\tshowFileInfo(file,argv)\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\tshowFiles(v.FoundFile)\n\t\t\t\tfmt.Printf(\"\\n\")\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc showMatchFile(filev []os.FileInfo, npat,dir string, argv[]string)(string,bool){\n\tfname := \"\"\n\tfound := false\n\tfor _,v := range filev {\n\t\tmatch, _ := filepath.Match(npat,(v.Name()))\n\t\tif match {\n\t\t\tfname = v.Name()\n\t\t\tfound = true\n\t\t\t\/\/fmt.Printf(\"[%d] %s\\n\",i,v.Name())\n\t\t\tshowIfExecutable(fname,dir,argv)\n\t\t}\n\t}\n\treturn fname,found\n}\nfunc showIfExecutable(name,dir string,argv[]string)(ffullpath string,ffound bool){\n\tvar fullpath string\n\tif strBegins(name,DIRSEP){\n\t\tfullpath = name\n\t}else{\n\t\tfullpath = dir + DIRSEP + name\n\t}\n\tfi, err := os.Stat(fullpath)\n\tif err != nil {\n\t\tfullpath = dir + DIRSEP + name + \".go\"\n\t\tfi, err = os.Stat(fullpath)\n\t}\n\tif err == nil {\n\t\tfm := fi.Mode()\n\t\tif fm.IsRegular() {\n\t\t  \/\/ R_OK=4, W_OK=2, X_OK=1, F_OK=0\n\t\t  if syscall.Access(fullpath,5) == nil {\n\t\t\tffullpath = fullpath\n\t\t\tffound = true\n\t\t\tif ! isin(\"-s\", argv) {\n\t\t\t\tshowFileInfo(fullpath,argv)\n\t\t\t}\n\t\t  }\n\t\t}\n\t}\n\treturn ffullpath, ffound\n}\nfunc which(list string, argv []string) (fullpathv []string, itis bool){\n\tif len(argv) <= 1 {\n\t\tfmt.Printf(\"Usage: which comand [-s] [-a] [-ls]\\n\")\n\t\treturn []string{\"\"}, false\n\t}\n\tpath := argv[1]\n\tif strBegins(path,\"\/\") {\n\t\t\/\/ should check if excecutable?\n\t\t_,exOK := showIfExecutable(path,\"\/\",argv)\n\t\tfmt.Printf(\"--D-- %v exOK=%v\\n\",path,exOK)\n\t\treturn []string{path},exOK\n\t}\n\tpathenv, efound := os.LookupEnv(list)\n\tif ! efound {\n\t\tfmt.Printf(\"--E-- which: no \\\"%s\\\" environment\\n\",list)\n\t\treturn []string{\"\"}, false\n\t}\n\tshowall := isin(\"-a\",argv) || 0 <= strings.Index(path,\"*\")\n\tdirv := strings.Split(pathenv,PATHSEP)\n\tffound := false\n\tffullpath := path\n\tfor _, dir := range dirv {\n\t\tif 0 <= strings.Index(path,\"*\") { \/\/ by wild-card\n\t\t\tlist,_ := ioutil.ReadDir(dir)\n\t\t\tffullpath, ffound = showMatchFile(list,path,dir,argv)\n\t\t}else{\n\t\t\tffullpath, ffound = showIfExecutable(path,dir,argv)\n\t\t}\n\t\t\/\/if ffound && !isin(\"-a\", argv) {\n\t\tif ffound && !showall {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn []string{ffullpath}, ffound\n}\n\nfunc stripLeadingWSParg(argv[]string)([]string){\n\tfor ; 0 < len(argv); {\n\t\tif len(argv[0]) == 0 {\n\t\t\targv = argv[1:]\n\t\t}else{\n\t\t\tbreak\n\t\t}\n\t}\n\treturn argv\n}\nfunc xEval(argv []string, nlend bool){\n\targv = stripLeadingWSParg(argv)\n\tif len(argv) == 0 {\n\t\tfmt.Printf(\"eval [%%format] [Go-expression]\\n\")\n\t\treturn\n\t}\n\tpfmt := \"%v\"\n\tif argv[0][0] == '%' {\n\t\tpfmt = argv[0]\n\t\targv = argv[1:]\n\t}\n\tif len(argv) == 0 {\n\t\treturn\n\t}\n\tgocode := strings.Join(argv,\" \");\n\t\/\/fmt.Printf(\"eval [%v] [%v]\\n\",pfmt,gocode)\n\tfset := token.NewFileSet()\n\trval, _ := types.Eval(fset,nil,token.NoPos,gocode)\n\tfmt.Printf(pfmt,rval.Value)\n\tif nlend { fmt.Printf(\"\\n\") }\n}\n\nfunc getval(name string) (found bool, val int) {\n\t\/* should expand the name here *\/\n\tif name == \"gsh.pid\" {\n\t\treturn true, os.Getpid()\n\t}else\n\tif name == \"gsh.ppid\" {\n\t\treturn true, os.Getppid()\n\t}\n\treturn false, 0\n}\n\nfunc echo(argv []string, nlend bool){\n\tfor ai := 1; ai < len(argv); ai++ {\n\t\tif 1 < ai {\n\t\t\tfmt.Printf(\" \");\n\t\t}\n\t\targ := argv[ai]\n\t\tfound, val := getval(arg)\n\t\tif found {\n\t\t\tfmt.Printf(\"%d\",val)\n\t\t}else{\n\t\t\tfmt.Printf(\"%s\",arg)\n\t\t}\n\t}\n\tif nlend {\n\t\tfmt.Printf(\"\\n\");\n\t}\n}\n\nfunc resfile() string {\n\treturn \"gsh.tmp\"\n}\n\/\/var resF *File\nfunc resmap() {\n\t\/\/_ , err := os.OpenFile(resfile(), os.O_RDWR|os.O_CREATE, os.ModeAppend)\n\t\/\/ https:\/\/developpaper.com\/solution-to-golang-bad-file-descriptor-problem\/\n\t_ , err := os.OpenFile(resfile(), os.O_RDWR|os.O_CREATE, 0600)\n\tif err != nil {\n\t\tfmt.Printf(\"refF could not open: %s\\n\",err)\n\t}else{\n\t\tfmt.Printf(\"refF opened\\n\")\n\t}\n}\n\n\/\/ @@2020-0821\nfunc gshScanArg(str string,strip int)(argv []string){\n\tvar si = 0\n\tvar sb = 0\n\tvar inBracket = 0\n\tvar arg1 = make([]byte,LINESIZE)\n\tvar ax = 0\n\tdebug := false\n\n\tfor ; si < len(str); si++ {\n\t\tif str[si] != ' ' {\n\t\t\tbreak\n\t\t}\n\t}\n\tsb = si\n\tfor ; si < len(str); si++ {\n\t\tif sb <= si {\n\t\t\tif debug {\n\t\t\t\tfmt.Printf(\"--Da- +%d %2d-%2d %s ... %s\\n\",\n\t\t\t\t\tinBracket,sb,si,arg1[0:ax],str[si:])\n\t\t\t}\n\t\t}\n\t\tch := str[si]\n\t\tif ch  == '{' {\n\t\t\tinBracket += 1\n\t\t\tif 0 < strip && inBracket <= strip {\n\t\t\t\t\/\/fmt.Printf(\"stripLEV %d <= %d?\\n\",inBracket,strip)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif 0 < inBracket {\n\t\t\tif ch == '}' {\n\t\t\t\tinBracket -= 1\n\t\t\t\tif 0 < strip && inBracket < strip {\n\t\t\t\t\t\/\/fmt.Printf(\"stripLEV %d <  %d?\\n\",inBracket,strip)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\targ1[ax] = ch\n\t\t\tax += 1\n\t\t\tcontinue\n\t\t}\n\t\tif str[si] == ' ' {\n\t\t\targv = append(argv,string(arg1[0:ax]))\n\t\t\tif debug {\n\t\t\t\tfmt.Printf(\"--Da- [%v][%v-%v] %s ... %s\\n\",\n\t\t\t\t\t-1+len(argv),sb,si,str[sb:si],string(str[si:]))\n\t\t\t}\n\t\t\tsb = si+1\n\t\t\tax = 0\n\t\t\tcontinue\n\t\t}\n\t\targ1[ax] = ch\n\t\tax += 1\n\t}\n\tif sb < si {\n\t\targv = append(argv,string(arg1[0:ax]))\n\t\tif debug {\n\t\t\tfmt.Printf(\"--Da- [%v][%v-%v] %s ... %s\\n\",\n\t\t\t\t-1+len(argv),sb,si,string(arg1[0:ax]),string(str[si:]))\n\t\t}\n\t}\n\tif debug {\n\t\tfmt.Printf(\"--Da- %d [%s] => [%d]%v\\n\",strip,str,len(argv),argv)\n\t}\n\treturn argv\n}\n\n\/\/ should get stderr (into tmpfile ?) and return\nfunc (gsh*GshContext)Popen(name,mode string)(pin*os.File,pout*os.File,err bool){\n\tvar pv = []int{-1,-1}\n\tsyscall.Pipe(pv)\n\n\txarg := gshScanArg(name,1)\n\tname = strings.Join(xarg,\" \")\n\n\tpin = os.NewFile(uintptr(pv[0]),\"StdoutOf-{\"+name+\"}\")\n\tpout = os.NewFile(uintptr(pv[1]),\"StdinOf-{\"+name+\"}\")\n\tfdix := 0\n\tdir := \"?\"\n\tif mode == \"r\" {\n\t\tdir = \"<\"\n\t\tfdix = 1 \/\/ read from the stdout of the process\n\t}else{\n\t\tdir = \">\"\n\t\tfdix = 0 \/\/ write to the stdin of the process\n\t}\n\tgshPA := gsh.gshPA\n\tsavfd := gshPA.Files[fdix]\n\n\tvar fd uintptr = 0\n\tif mode == \"r\" {\n\t\tfd = pout.Fd()\n\t\tgshPA.Files[fdix] = pout.Fd()\n\t}else{\n\t\tfd = pin.Fd()\n\t\tgshPA.Files[fdix] = pin.Fd()\n\t}\n\t\t\/\/ should do this by Goroutine?\n\t\tif false {\n\t\t\tfmt.Printf(\"--Ip- Opened fd[%v] %s %v\\n\",fd,dir,name)\n\t\t\tfmt.Printf(\"--RED1 [%d,%d,%d]->[%d,%d,%d]\\n\",\n\t\t\t\tos.Stdin.Fd(),os.Stdout.Fd(),os.Stderr.Fd(),\n\t\t\t\tpin.Fd(),pout.Fd(),pout.Fd())\n\t\t}\n\t\t\tsavi := os.Stdin\n\t\t\tsavo := os.Stdout\n\t\t\tsave := os.Stderr\n\t\t\tos.Stdin  = pin\n\t\t\tos.Stdout = pout\n\t\t\tos.Stderr = pout\n\t\tgsh.BackGround = true\n\t\tgsh.gshelllh(name)\n\t\tgsh.BackGround = false\n\t\t\tos.Stdin  = savi\n\t\t\tos.Stdout = savo\n\t\t\tos.Stderr = save\n\n\tgshPA.Files[fdix] = savfd\n\treturn pin,pout,false\n}\n\n\/\/ <a name=\"ex-commands\">External commands<\/a>\nfunc (gsh*GshContext)excommand(exec bool, argv []string) (notf bool,exit bool) {\n\tif gsh.CmdTrace { fmt.Printf(\"--I-- excommand[%v](%v)\\n\",exec,argv) }\n\n\tgshPA := gsh.gshPA\n\tfullpathv, itis := which(\"PATH\",[]string{\"which\",argv[0],\"-s\"})\n\tif itis == false {\n\t\treturn true,false\n\t}\n\tfullpath := fullpathv[0]\n\targv = unescapeWhiteSPV(argv)\n\tif 0 < strings.Index(fullpath,\".go\") {\n\t\tnargv := argv \/\/ []string{}\n\t\tgofullpathv, itis := which(\"PATH\",[]string{\"which\",\"go\",\"-s\"})\n\t\tif itis == false {\n\t\t\tfmt.Printf(\"--F-- Go not found\\n\")\n\t\t\treturn false,true\n\t\t}\n\t\tgofullpath := gofullpathv[0]\n\t\tnargv = []string{ gofullpath, \"run\", fullpath }\n\t\tfmt.Printf(\"--I-- %s {%s %s %s}\\n\",gofullpath,\n\t\t\tnargv[0],nargv[1],nargv[2])\n\t\tif exec {\n\t\t\tsyscall.Exec(gofullpath,nargv,os.Environ())\n\t\t}else{\n\t\t\tpid, _ := syscall.ForkExec(gofullpath,nargv,&gshPA)\n\t\t\tif gsh.BackGround {\n\t\t\t\tfmt.Fprintf(stderr,\"--Ip- in Background pid[%d]%d(%v)\\n\",pid,len(argv),nargv)\n\t\t\t\tgsh.BackGroundJobs = append(gsh.BackGroundJobs,pid)\n\t\t\t}else{\n\t\t\t\trusage := syscall.Rusage {}\n\t\t\t\tsyscall.Wait4(pid,nil,0,&rusage)\n\t\t\t\tgsh.LastRusage = rusage\n\t\t\t\tgsh.CmdCurrent.Rusagev[1] = rusage\n\t\t\t}\n\t\t}\n\t}else{\n\t\tif exec {\n\t\t\tsyscall.Exec(fullpath,argv,os.Environ())\n\t\t}else{\n\t\t\tpid, _ := syscall.ForkExec(fullpath,argv,&gshPA)\n\t\t\t\/\/fmt.Printf(\"[%d]\\n\",pid); \/\/ '&' to be background\n\t\t\tif gsh.BackGround {\n\t\t\t\tfmt.Fprintf(stderr,\"--Ip- in Background pid[%d]%d(%v)\\n\",pid,len(argv),argv)\n\t\t\t\tgsh.BackGroundJobs = append(gsh.BackGroundJobs,pid)\n\t\t\t}else{\n\t\t\t\trusage := syscall.Rusage {}\n\t\t\t\tsyscall.Wait4(pid,nil,0,&rusage);\n\t\t\t\tgsh.LastRusage = rusage\n\t\t\t\tgsh.CmdCurrent.Rusagev[1] = rusage\n\t\t\t}\n\t\t}\n\t}\n\treturn false,false\n}\n\n\/\/ <a name=\"builtin\">Builtin Commands<\/a>\nfunc (gshCtx *GshContext) sleep(argv []string) {\n\tif len(argv) < 2 {\n\t\tfmt.Printf(\"Sleep 100ms, 100us, 100ns, ...\\n\")\n\t\treturn\n\t}\n\tduration := argv[1];\n\td, err := time.ParseDuration(duration)\n\tif err != nil {\n\t\td, err = time.ParseDuration(duration+\"s\")\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"duration ? %s (%s)\\n\",duration,err)\n\t\t\treturn\n\t\t}\n\t}\n\t\/\/fmt.Printf(\"Sleep %v\\n\",duration)\n\ttime.Sleep(d)\n\tif 0 < len(argv[2:]) {\n\t\tgshCtx.gshellv(argv[2:])\n\t}\n}\nfunc (gshCtx *GshContext)repeat(argv []string) {\n\tif len(argv) < 2 {\n\t\treturn\n\t}\n\tstart0 := time.Now()\n\tfor ri,_ := strconv.Atoi(argv[1]); 0 < ri; ri-- {\n\t\tif 0 < len(argv[2:]) {\n\t\t\t\/\/start := time.Now()\n\t\t\tgshCtx.gshellv(argv[2:])\n\t\t\tend := time.Now()\n\t\t\telps := end.Sub(start0);\n\t\t\tif( 1000000000 < elps ){\n\t\t\t\tfmt.Printf(\"(repeat#%d %v)\\n\",ri,elps);\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (gshCtx *GshContext)gen(argv []string) {\n\tgshPA := gshCtx.gshPA\n\tif len(argv) < 2 {\n\t\tfmt.Printf(\"Usage: %s N\\n\",argv[0])\n\t\treturn\n\t}\n\t\/\/ should br repeated by \"repeat\" command\n\tcount, _ := strconv.Atoi(argv[1])\n\tfd := gshPA.Files[1] \/\/ Stdout\n\tfile := os.NewFile(fd,\"internalStdOut\")\n\tfmt.Printf(\"--I-- Gen. Count=%d to [%d]\\n\",count,file.Fd())\n\t\/\/buf := []byte{}\n\toutdata := \"0123 5678 0123 5678 0123 5678 0123 5678\\r\"\n\tfor gi := 0; gi < count; gi++ {\n\t\tfile.WriteString(outdata)\n\t}\n\t\/\/file.WriteString(\"\\n\")\n\tfmt.Printf(\"\\n(%d B)\\n\",count*len(outdata));\n\t\/\/file.Close()\n}\n\n\/\/ <a name=\"rexec\">Remote Execution<\/a> \/\/ 2020-0820\nfunc Elapsed(from time.Time)(string){\n\telps := time.Now().Sub(from)\n\tif 1000000000 < elps {\n\t\treturn fmt.Sprintf(\"[%5d.%02ds]\",elps\/1000000000,(elps%1000000000)\/10000000)\n\t}else\n\tif 1000000 < elps {\n\t\treturn fmt.Sprintf(\"[%3d.%03dms]\",elps\/1000000,(elps%1000000)\/1000)\n\t}else{\n\t\treturn fmt.Sprintf(\"[%3d.%03dus]\",elps\/1000,(elps%1000))\n\t}\n}\nfunc abbtime(nanos int64)(string){\n\tif 1000000000 < nanos {\n\t\treturn fmt.Sprintf(\"%d.%02ds\",nanos\/1000000000,(nanos%1000000000)\/10000000)\n\t}else\n\tif 1000000 < nanos {\n\t\treturn fmt.Sprintf(\"%d.%03dms\",nanos\/1000000,(nanos%1000000)\/1000)\n\t}else{\n\t\treturn fmt.Sprintf(\"%d.%03dus\",nanos\/1000,(nanos%1000))\n\t}\n}\nfunc abssize(size int64)(string){\n\tfsize := float64(size)\n\tif 1024*1024*1024 < size {\n\t\treturn fmt.Sprintf(\"%.2fGiB\",fsize\/(1024*1024*1024))\n\t}else\n\tif 1024*1024 < size {\n\t\treturn fmt.Sprintf(\"%.3fMiB\",fsize\/(1024*1024))\n\t}else{\n\t\treturn fmt.Sprintf(\"%.3fKiB\",fsize\/1024)\n\t}\n}\nfunc absize(size int64)(string){\n\tfsize := float64(size)\n\tif 1024*1024*1024 < size {\n\t\treturn fmt.Sprintf(\"%8.2fGiB\",fsize\/(1024*1024*1024))\n\t}else\n\tif 1024*1024 < size {\n\t\treturn fmt.Sprintf(\"%8.3fMiB\",fsize\/(1024*1024))\n\t}else{\n\t\treturn fmt.Sprintf(\"%8.3fKiB\",fsize\/1024)\n\t}\n}\nfunc abbspeed(totalB int64,ns int64)(string){\n\tMBs := (float64(totalB)\/1000000) \/ (float64(ns)\/1000000000)\n\tif 1000 <= MBs {\n\t\treturn fmt.Sprintf(\"%6.3fGB\/s\",MBs\/1000)\n\t}\n\tif 1 <= MBs {\n\t\treturn fmt.Sprintf(\"%6.3fMB\/s\",MBs)\n\t}else{\n\t\treturn fmt.Sprintf(\"%6.3fKB\/s\",MBs*1000)\n\t}\n}\nfunc abspeed(totalB int64,ns time.Duration)(string){\n\tMBs := (float64(totalB)\/1000000) \/ (float64(ns)\/1000000000)\n\tif 1000 <= MBs {\n\t\treturn fmt.Sprintf(\"%6.3fGBps\",MBs\/1000)\n\t}\n\tif 1 <= MBs {\n\t\treturn fmt.Sprintf(\"%6.3fMBps\",MBs)\n\t}else{\n\t\treturn fmt.Sprintf(\"%6.3fKBps\",MBs*1000)\n\t}\n}\nfunc fileRelay(what string,in*os.File,out*os.File,size int64,bsiz int)(wcount int64){\n\tStart := time.Now()\n\tbuff := make([]byte,bsiz)\n\tvar total int64 = 0\n\tvar rem int64 = size\n\tnio := 0\n\tPrev := time.Now()\n\tvar PrevSize int64 = 0\n\n\tfmt.Printf(Elapsed(Start)+\"--In- X: %s (%v\/%v\/%v) START\\n\",\n\t\twhat,absize(total),size,nio)\n\n\tfor i:= 0; ; i++ {\n\t\tvar len = bsiz\n\t\tif int(rem) < len {\n\t\t\tlen = int(rem)\n\t\t}\n\t\tNow := time.Now()\n\t\tElps := Now.Sub(Prev);\n\t\tif 1000000000 < Now.Sub(Prev) {\n\t\t\tfmt.Printf(Elapsed(Start)+\"--In- X: %s (%v\/%v\/%v) %s\\n\",\n\t\t\t\twhat,absize(total),size,nio,\n\t\t\t\tabspeed((total-PrevSize),Elps))\n\t\t\tPrev = Now;\n\t\t\tPrevSize = total\n\t\t}\n\t\trlen := len\n\t\tif in != nil {\n\t\t\t\/\/ should watch the disconnection of out\n\t\t\trcc,err := in.Read(buff[0:rlen])\n\t\t\tif err != nil {\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"--En- X: %s read(%v,%v)<%v\\n\",\n\t\t\t\t\twhat,rcc,err,in.Name())\n\t\t\t\tbreak\n\t\t\t}\n\t\t\trlen = rcc\n\t\t\tif string(buff[0:10]) == \"((SoftEOF \" {\n\t\t\t\tvar ecc int64 = 0\n\t\t\t\tfmt.Sscanf(string(buff),\"((SoftEOF %v\",&ecc)\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"--En- X: %s Recv ((SoftEOF %v))\/%v\\n\",\n\t\t\t\t\twhat,ecc,total)\n\t\t\t\tif ecc == total {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\twlen := rlen\n\t\tif out != nil {\n\t\t\twcc,err := out.Write(buff[0:rlen])\n\t\t\tif err != nil {\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"-En-- X: %s write(%v,%v)>%v\\n\",\n\t\t\t\t\twhat,wcc,err,out.Name())\n\t\t\t\tbreak\n\t\t\t}\n\t\t\twlen = wcc\n\t\t}\n\t\tif wlen < rlen {\n\t\t\tfmt.Printf(Elapsed(Start)+\"--En- X: %s incomplete write (%v\/%v)\\n\",\n\t\t\t\twhat,wlen,rlen)\n\t\t\tbreak;\n\t\t}\n\n\t\tnio += 1\n\t\ttotal += int64(rlen)\n\t\trem -= int64(rlen)\n\t\tif rem <= 0 {\n\t\t\tbreak\n\t\t}\n\t}\n\tDone := time.Now()\n\tElps := float64(Done.Sub(Start))\/1000000000 \/\/Seconds\n\tTotalMB := float64(total)\/1000000 \/\/MB\n\tMBps := TotalMB \/ Elps\n\tfmt.Printf(Elapsed(Start)+\"--In- X: %s (%v\/%v\/%v) %v %.3fMB\/s\\n\",\n\t\twhat,total,size,nio,absize(total),MBps)\n\treturn total\n}\nfunc tcpPush(clnt *os.File){\n\t\/\/ shrink socket buffer and recover\n\tusleep(100);\n}\nfunc (gsh*GshContext)RexecServer(argv[]string){\n\tdebug := true\n\tStart0 := time.Now()\n\tStart := Start0\n\/\/\tif local == \":\" { local = \"0.0.0.0:9999\" }\n\tlocal := \"0.0.0.0:9999\"\n\n\tif 0 < len(argv) {\n\t\tif argv[0] == \"-s\" {\n\t\t\tdebug = false\n\t\t\targv = argv[1:]\n\t\t}\n\t}\n\tif 0 < len(argv) {\n\t\targv = argv[1:]\n\t}\n\tport, err := net.ResolveTCPAddr(\"tcp\",local);\n\tif err != nil {\n\t\tfmt.Printf(\"--En- S: Address error: %s (%s)\\n\",local,err)\n\t\treturn\n\t}\n\tfmt.Printf(Elapsed(Start)+\"--In- S: Listening at %s...\\n\",local);\n\tsconn, err := net.ListenTCP(\"tcp\", port)\n\tif err != nil {\n\t\tfmt.Printf(Elapsed(Start)+\"--En- S: Listen error: %s (%s)\\n\",local,err)\n\t\treturn\n\t}\n\n\treqbuf := make([]byte,LINESIZE)\n\tres := \"\"\n\tfor {\n\t\tfmt.Printf(Elapsed(Start0)+\"--In- S: Listening at %s...\\n\",local);\n\t\taconn, err := sconn.AcceptTCP()\n\t\tStart = time.Now()\n\t\tif err != nil {\n\t\t\tfmt.Printf(Elapsed(Start)+\"--En- S: Accept error: %s (%s)\\n\",local,err)\n\t\t\treturn\n\t\t}\n\t\tclnt, _ := aconn.File()\n\t\tfd := clnt.Fd()\n\t\tar := aconn.RemoteAddr()\n\t\tif debug { fmt.Printf(Elapsed(Start0)+\"--In- S: Accepted TCP at %s [%d] <- %v\\n\",\n\t\t\tlocal,fd,ar) }\n\t\tres = fmt.Sprintf(\"220 GShell\/%s Server\\r\\n\",VERSION)\n\t\tfmt.Fprintf(clnt,\"%s\",res)\n\t\tif debug { fmt.Printf(Elapsed(Start)+\"--In- S: %s\",res) }\n\t\tcount, err := clnt.Read(reqbuf)\n\t\tif err != nil {\n\t\t\tfmt.Printf(Elapsed(Start)+\"--En- C: (%v %v) %v\",\n\t\t\t\tcount,err,string(reqbuf))\n\t\t}\n\t\treq := string(reqbuf[:count])\n\t\tif debug { fmt.Printf(Elapsed(Start)+\"--In- C: %v\",string(req)) }\n\t\treqv := strings.Split(string(req),\"\\r\")\n\t\tcmdv := gshScanArg(reqv[0],0)\n\t\t\/\/cmdv := strings.Split(reqv[0],\" \")\n\t\tswitch cmdv[0] {\n\t\t\tcase \"HELO\":\n\t\t\t\tres = fmt.Sprintf(\"250 %v\",req)\n\t\t\tcase \"GET\":\n\t\t\t\t\/\/ download {remotefile|-zN} [localfile]\n\t\t\t\tvar dsize int64 = 32*1024*1024\n\t\t\t\tvar bsize int = 64*1024\n\t\t\t\tvar fname string = \"\"\n\t\t\t\tvar in *os.File = nil\n\t\t\t\tvar pseudoEOF = false\n\t\t\t\tif 1 < len(cmdv) {\n\t\t\t\t\tfname = cmdv[1]\n\t\t\t\t\tif strBegins(fname,\"-z\") {\n\t\t\t\t\t\tfmt.Sscanf(fname[2:],\"%d\",&dsize)\n\t\t\t\t\t}else\n\t\t\t\t\tif strBegins(fname,\"{\") {\n\t\t\t\t\t\txin,xout,err := gsh.Popen(fname,\"r\")\n\t\t\t\t\t\tif err {\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\txout.Close()\n\t\t\t\t\t\t\tdefer xin.Close()\n\t\t\t\t\t\t\tin = xin\n\t\t\t\t\t\t\tdsize = MaxStreamSize\n\t\t\t\t\t\t\tpseudoEOF = true\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\txin,err := os.Open(fname)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tfmt.Printf(\"--En- GET (%v)\\n\",err)\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tdefer xin.Close()\n\t\t\t\t\t\t\tin = xin\n\t\t\t\t\t\t\tfi,_ := xin.Stat()\n\t\t\t\t\t\t\tdsize = fi.Size()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\/\/fmt.Printf(Elapsed(Start)+\"--In- GET %v:%v\\n\",dsize,bsize)\n\t\t\t\tres = fmt.Sprintf(\"200 %v\\r\\n\",dsize)\n\t\t\t\tfmt.Fprintf(clnt,\"%v\",res)\n\t\t\t\ttcpPush(clnt); \/\/ should be separated as line in receiver\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"--In- S: %v\",res)\n\t\t\t\twcount := fileRelay(\"SendGET\",in,clnt,dsize,bsize)\n\t\t\t\tif pseudoEOF {\n\t\t\t\t\tin.Close() \/\/ pipe from the command\n\t\t\t\t\t\/\/ show end of stream data (its size) by OOB?\n\t\t\t\t\tSoftEOF := fmt.Sprintf(\"((SoftEOF %v))\",wcount)\n\t\t\t\t\tfmt.Printf(Elapsed(Start)+\"--In- S: Send %v\\n\",SoftEOF)\n\n\t\t\t\t\ttcpPush(clnt); \/\/ to let SoftEOF data apper at the top of recevied data\n\t\t\t\t\tfmt.Fprintf(clnt,\"%v\\r\\n\",SoftEOF)\n\t\t\t\t\ttcpPush(clnt); \/\/ to let SoftEOF alone in a packet (separate with 200 OK)\n\t\t\t\t\t\t\/\/ with client generated random?\n\t\t\t\t\t\/\/fmt.Printf(\"--In- L: close %v (%v)\\n\",in.Fd(),in.Name())\n\t\t\t\t}\n\t\t\t\tres = fmt.Sprintf(\"200 GET done\\r\\n\")\n\t\t\tcase \"PUT\":\n\t\t\t\t\/\/ upload {srcfile|-zN} [dstfile]\n\t\t\t\tvar dsize int64 = 32*1024*1024\n\t\t\t\tvar bsize int = 64*1024\n\t\t\t\tvar fname string = \"\"\n\t\t\t\tvar out *os.File = nil\n\t\t\t\tif 1 < len(cmdv) { \/\/ localfile\n\t\t\t\t\tfmt.Sscanf(cmdv[1],\"%d\",&dsize)\n\t\t\t\t}\n\t\t\t\tif 2 < len(cmdv) {\n\t\t\t\t\tfname = cmdv[2]\n\t\t\t\t\tif fname == \"-\" {\n\t\t\t\t\t\t\/\/ nul dev\n\t\t\t\t\t}else\n\t\t\t\t\tif strBegins(fname,\"{\") {\n\t\t\t\t\t\txin,xout,err := gsh.Popen(fname,\"w\")\n\t\t\t\t\t\tif err {\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\txin.Close()\n\t\t\t\t\t\t\tdefer xout.Close()\n\t\t\t\t\t\t\tout = xout\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\/\/ should write to temporary file\n\t\t\t\t\t\/\/ should suppress ^C on tty\n\t\t\txout,err := os.OpenFile(fname,os.O_CREATE|os.O_RDWR|os.O_TRUNC,0600)\n\t\t\t\/\/fmt.Printf(\"--In- S: open(%v) out(%v) err(%v)\\n\",fname,xout,err)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\tfmt.Printf(\"--En- PUT (%v)\\n\",err)\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\tout = xout\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"--In- L: open(%v,w) %v (%v)\\n\",\n\t\t\t\t\tfname,local,err)\n\t\t\t\t}\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"--In- PUT %v (\/%v)\\n\",dsize,bsize)\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"--In- S: 200 %v OK\\r\\n\",dsize)\n\t\t\t\tfmt.Fprintf(clnt,\"200 %v OK\\r\\n\",dsize)\n\t\t\t\tfileRelay(\"RecvPUT\",clnt,out,dsize,bsize)\n\t\t\t\tres = fmt.Sprintf(\"200 PUT done\\r\\n\")\n\t\t\tdefault:\n\t\t\t\tres = fmt.Sprintf(\"400 What? %v\",req)\n\t\t}\n\t\tswcc,serr := clnt.Write([]byte(res))\n\t\tif serr != nil {\n\t\t\tfmt.Printf(Elapsed(Start)+\"--In- S: (wc=%v er=%v) %v\",swcc,serr,res)\n\t\t}else{\n\t\t\tfmt.Printf(Elapsed(Start)+\"--In- S: %v\",res)\n\t\t}\n\t\taconn.Close();\n\t\tclnt.Close();\n\t}\n\tsconn.Close();\n}\nfunc (gsh*GshContext)RexecClient(argv[]string)(int,string){\n\tdebug := true\n\tStart := time.Now()\n\tif len(argv) == 1 {\n\t\treturn -1,\"EmptyARG\"\n\t}\n\targv = argv[1:]\n\tif argv[0] == \"-serv\" {\n\t\tgsh.RexecServer(argv[1:])\n\t\treturn 0,\"Server\"\n\t}\n\tremote := \"0.0.0.0:9999\"\n\tif argv[0][0] == '@' {\n\t\tremote = argv[0][1:]\n\t\targv = argv[1:]\n\t}\n\tif argv[0] == \"-s\" {\n\t\tdebug = false\n\t\targv = argv[1:]\n\t}\n\tdport, err := net.ResolveTCPAddr(\"tcp\",remote);\n\tif err != nil {\n\t\tfmt.Printf(Elapsed(Start)+\"Address error: %s (%s)\\n\",remote,err)\n\t\treturn -1,\"AddressError\"\n\t}\n\tfmt.Printf(Elapsed(Start)+\"--In- C: Connecting to %s\\n\",remote)\n\tserv, err := net.DialTCP(\"tcp\",nil,dport)\n\tif err != nil {\n\t\tfmt.Printf(Elapsed(Start)+\"Connection error: %s (%s)\\n\",remote,err)\n\t\treturn -1,\"CannotConnect\"\n\t}\n\tif debug {\n\t\tal := serv.LocalAddr()\n\t\tfmt.Printf(Elapsed(Start)+\"--In- C: Connected to %v <- %v\\n\",remote,al)\n\t}\n\n\treq := \"\"\n\tres := make([]byte,LINESIZE)\n\tcount,err := serv.Read(res)\n\tif err != nil {\n\t\tfmt.Printf(\"--En- S: (%3d,%v) %v\",count,err,string(res))\n\t}\n\tif debug { fmt.Printf(Elapsed(Start)+\"--In- S: %v\",string(res)) }\n\n\tif argv[0] == \"GET\" {\n\t\tsavPA := gsh.gshPA\n\t\tvar bsize int = 64*1024\n\t\treq = fmt.Sprintf(\"%v\\r\\n\",strings.Join(argv,\" \"))\n\t\tfmt.Printf(Elapsed(Start)+\"--In- C: %v\",req)\n\t\tfmt.Fprintf(serv,req)\n\t\tcount,err = serv.Read(res)\n\t\tif err != nil {\n\t\t}else{\n\t\t\tvar dsize int64 = 0\n\t\t\tvar out *os.File = nil\n\t\t\tvar out_tobeclosed *os.File = nil\n\t\t\tvar fname string = \"\"\n\t\t\tvar rcode int = 0\n\t\t\tvar pid int = -1\n\t\t\tfmt.Sscanf(string(res),\"%d %d\",&rcode,&dsize)\n\t\t\tfmt.Printf(Elapsed(Start)+\"--In- S: %v\",string(res[0:count]))\n\t\t\tif 3 <= len(argv) {\n\t\t\t\tfname = argv[2]\n\t\t\t\tif strBegins(fname,\"{\") {\n\t\t\t\t\txin,xout,err := gsh.Popen(fname,\"w\")\n\t\t\t\t\tif err {\n\t\t\t\t\t}else{\n\t\t\t\t\t\txin.Close()\n\t\t\t\t\t\tdefer xout.Close()\n\t\t\t\t\t\tout = xout\n\t\t\t\t\t\tout_tobeclosed = xout\n\t\t\t\t\t\tpid = 0 \/\/ should be its pid\n\t\t\t\t\t}\n\t\t\t\t}else{\n\t\t\t\t\t\/\/ should write to temporary file\n\t\t\t\t\t\/\/ should suppress ^C on tty\n\t\t\t\t\txout,err := os.OpenFile(fname,os.O_CREATE|os.O_RDWR|os.O_TRUNC,0600)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tfmt.Print(\"--En- %v\\n\",err)\n\t\t\t\t\t}\n\t\t\t\t\tout = xout\n\t\t\t\t\t\/\/fmt.Printf(\"--In-- %d > %s\\n\",out.Fd(),fname)\n\t\t\t\t}\n\t\t\t}\n\t\t\tin,_ := serv.File()\n\t\t\tfileRelay(\"RecvGET\",in,out,dsize,bsize)\n\t\t\tif 0 <= pid {\n\t\t\t\tgsh.gshPA = savPA \/\/ recovery of Fd(), and more?\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"--In- L: close Pipe > %v\\n\",fname)\n\t\t\t\tout_tobeclosed.Close()\n\t\t\t\t\/\/syscall.Wait4(pid,nil,0,nil) \/\/@@\n\t\t\t}\n\t\t}\n\t}else\n\tif argv[0] == \"PUT\" {\n\t\tremote, _ := serv.File()\n\t\tvar local *os.File = nil\n\t\tvar dsize int64 = 32*1024*1024\n\t\tvar bsize int = 64*1024\n\t\tvar ofile string = \"-\"\n\t\t\/\/fmt.Printf(\"--I-- Rex %v\\n\",argv)\n\t\tif 1 < len(argv) {\n\t\t\tfname := argv[1]\n\t\t\tif strBegins(fname,\"-z\") {\n\t\t\t\tfmt.Sscanf(fname[2:],\"%d\",&dsize)\n\t\t\t}else\n\t\t\tif strBegins(fname,\"{\") {\n\t\t\t\txin,xout,err := gsh.Popen(fname,\"r\")\n\t\t\t\tif err {\n\t\t\t\t}else{\n\t\t\t\t\txout.Close()\n\t\t\t\t\tdefer xin.Close()\n\t\t\t\t\t\/\/in = xin\n\t\t\t\t\tlocal = xin\n\t\t\t\t\tfmt.Printf(\"--In- [%d] < Upload output of %v\\n\",\n\t\t\t\t\t\tlocal.Fd(),fname)\n\t\t\t\t\tofile = \"-from.\"+fname\n\t\t\t\t\tdsize = MaxStreamSize\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\txlocal,err := os.Open(fname)\n\t\t\t\tif err != nil {\n\t\t\t\t\tfmt.Printf(\"--En- (%s)\\n\",err)\n\t\t\t\t\tlocal = nil\n\t\t\t\t}else{\n\t\t\t\t\tlocal = xlocal\n\t\t\t\t\tfi,_ := local.Stat()\n\t\t\t\t\tdsize = fi.Size()\n\t\t\t\t\tdefer local.Close()\n\t\t\t\t\t\/\/fmt.Printf(\"--I-- Rex in(%v \/ %v)\\n\",ofile,dsize)\n\t\t\t\t}\n\t\t\t\tofile = fname\n\t\t\t\tfmt.Printf(Elapsed(Start)+\"--In- L: open(%v,r)=%v %v (%v)\\n\",\n\t\t\t\t\tfname,dsize,local,err)\n\t\t\t}\n\t\t}\n\t\tif 2 < len(argv) && argv[2] != \"\" {\n\t\t\tofile = argv[2]\n\t\t\t\/\/fmt.Printf(\"(%d)%v B.ofile=%v\\n\",len(argv),argv,ofile)\n\t\t}\n\t\t\/\/fmt.Printf(Elapsed(Start)+\"--I-- Rex out(%v)\\n\",ofile)\n\t\tfmt.Printf(Elapsed(Start)+\"--In- PUT %v (\/%v)\\n\",dsize,bsize)\n\t\treq = fmt.Sprintf(\"PUT %v %v \\r\\n\",dsize,ofile)\n\t\tif debug { fmt.Printf(Elapsed(Start)+\"--In- C: %v\",req) }\n\t\tfmt.Fprintf(serv,\"%v\",req)\n\t\tcount,err = serv.Read(res)\n\t\tif debug { fmt.Printf(Elapsed(Start)+\"--In- S: %v\",string(res[0:count])) }\n\t\tfileRelay(\"SendPUT\",local,remote,dsize,bsize)\n\t}else{\n\t\treq = fmt.Sprintf(\"%v\\r\\n\",strings.Join(argv,\" \"))\n\t\tif debug { fmt.Printf(Elapsed(Start)+\"--In- C: %v\",req) }\n\t\tfmt.Fprintf(serv,\"%v\",req)\n\t\t\/\/fmt.Printf(\"--In- sending RexRequest(%v)\\n\",len(req))\n\t}\n\t\/\/fmt.Printf(Elapsed(Start)+\"--In- waiting RexResponse...\\n\")\n\tcount,err = serv.Read(res)\n\tress := \"\"\n\tif count == 0 {\n\t\tress = \"(nil)\\r\\n\"\n\t}else{\n\t\tress = string(res[:count])\n\t}\n\tif err != nil {\n\t\tfmt.Printf(Elapsed(Start)+\"--En- S: (%d,%v) %v\",count,err,ress)\n\t}else{\n\t\tfmt.Printf(Elapsed(Start)+\"--In- S: %v\",ress)\n\t}\n\tserv.Close()\n\t\/\/conn.Close()\n\n\tvar stat string\n\tvar rcode int\n\tfmt.Sscanf(ress,\"%d %s\",&rcode,&stat)\n\t\/\/fmt.Printf(\"--D-- Client: %v (%v)\",rcode,stat)\n\treturn rcode,ress\n}\n\n\/\/ <a name=\"remote-sh\">Remote Shell<\/a>\n\/\/ gcp file [...] { [host]:[port:][dir] | dir } \/\/ -p | -no-p\nfunc (gsh*GshContext)FileCopy(argv[]string){\n\tvar host = \"\"\n\tvar port = \"\"\n\tvar upload = false\n\tvar download = false\n\tvar xargv = []string{\"rex-gcp\"}\n\tvar srcv = []string{}\n\tvar dstv = []string{}\n\targv = argv[1:]\n\n\tfor _,v := range argv {\n\t\t\/*\n\t\tif v[0] == '-' { \/\/ might be a pseudo file (generated date)\n\t\t\tcontinue\n\t\t}\n\t\t*\/\n\t\tobj := strings.Split(v,\":\")\n\t\t\/\/fmt.Printf(\"%d %v %v\\n\",len(obj),v,obj)\n\t\tif 1 < len(obj) {\n\t\t\thost = obj[0]\n\t\t\tfile := \"\"\n\t\t\tif 0 < len(host) { \n\t\t\t\tgsh.LastServer.host = host\n\t\t\t}else{\n\t\t\t\thost = gsh.LastServer.host\n\t\t\t\tport = gsh.LastServer.port\n\t\t\t}\n\t\t\tif 2 < len(obj) {\n\t\t\t\tport = obj[1]\n\t\t\t\tif 0 < len(port) {\n\t\t\t\t\tgsh.LastServer.port = port\n\t\t\t\t}else{\n\t\t\t\t\tport = gsh.LastServer.port\n\t\t\t\t}\n\t\t\t\tfile = obj[2]\n\t\t\t}else{\n\t\t\t\tfile = obj[1]\n\t\t\t}\n\t\t\tif len(srcv) == 0 {\n\t\t\t\tdownload = true\n\t\t\t\tsrcv = append(srcv,file)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tupload = true\n\t\t\tdstv = append(dstv,file)\n\t\t\tcontinue\n\t\t}\n\t\t\/*\n\t\tidx := strings.Index(v,\":\")\n\t\tif 0 <= idx {\n\t\t\tremote = v[0:idx]\n\t\t\tif len(srcv) == 0 {\n\t\t\t\tdownload = true\n\t\t\t\tsrcv = append(srcv,v[idx+1:])\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tupload = true\n\t\t\tdstv = append(dstv,v[idx+1:])\n\t\t\tcontinue\n\t\t}\n\t\t*\/\n\t\tif download {\n\t\t\tdstv = append(dstv,v)\n\t\t}else{\n\t\t\tsrcv = append(srcv,v)\n\t\t}\n\t}\n\thostport := \"@\" + host + \":\" + port\n\tif upload {\n\t\tif host != \"\" { xargv = append(xargv,hostport) }\n\t\txargv = append(xargv,\"PUT\")\n\t\txargv = append(xargv,srcv[0:]...)\n\t\txargv = append(xargv,dstv[0:]...)\n\t\/\/fmt.Printf(\"--I-- FileCopy PUT gsh:\/\/%s\/%v < %v \/\/ %v\\n\",hostport,dstv,srcv,xargv)\n\tfmt.Printf(\"--I-- FileCopy PUT gsh:\/\/%s\/%v < %v\\n\",hostport,dstv,srcv)\n\t\tgsh.RexecClient(xargv)\n\t}else\n\tif download {\n\t\tif host != \"\" { xargv = append(xargv,hostport) }\n\t\txargv = append(xargv,\"GET\")\n\t\txargv = append(xargv,srcv[0:]...)\n\t\txargv = append(xargv,dstv[0:]...)\n\t\/\/fmt.Printf(\"--I-- FileCopy GET gsh:\/\/%v\/%v > %v \/\/ %v\\n\",hostport,srcv,dstv,xargv)\n\tfmt.Printf(\"--I-- FileCopy GET gsh:\/\/%v\/%v > %v\\n\",hostport,srcv,dstv)\n\t\tgsh.RexecClient(xargv)\n\t}else{\n\t}\n}\n\n\/\/ target\nfunc (gsh*GshContext)Trelpath(rloc string)(string){\n\tcwd, _ := os.Getwd()\n\tos.Chdir(gsh.RWD)\n\tos.Chdir(rloc)\n\ttwd, _ := os.Getwd()\n\tos.Chdir(cwd)\n\n\ttpath := twd + \"\/\" + rloc\n\treturn tpath\n}\n\/\/ join to rmote GShell - [user@]host[:port] or cd host:[port]:path\nfunc (gsh*GshContext)Rjoin(argv[]string){\n\tif len(argv) <= 1 {\n\t\tfmt.Printf(\"--I-- current server = %v\\n\",gsh.RSERV)\n\t\treturn\n\t}\n\tserv := argv[1]\n\tservv := strings.Split(serv,\":\")\n\tif 1 <= len(servv) {\n\t\tif servv[0] == \"lo\" {\n\t\t\tservv[0] = \"localhost\"\n\t\t}\n\t}\n\tswitch len(servv) {\n\t\tcase 1:\n\t\t\t\/\/if strings.Index(serv,\":\") < 0 {\n\t\t\tserv = servv[0] + \":\" + fmt.Sprintf(\"%d\",GSH_PORT)\n\t\t\t\/\/}\n\t\tcase 2: \/\/ host:port\n\t\t\tserv = strings.Join(servv,\":\")\n\t}\n\txargv := []string{\"rex-join\",\"@\"+serv,\"HELO\"}\n\trcode,stat := gsh.RexecClient(xargv)\n\tif (rcode \/ 100) == 2 {\n\t\tfmt.Printf(\"--I-- OK Joined (%v) %v\\n\",rcode,stat)\n\t\tgsh.RSERV = serv\n\t}else{\n\t\tfmt.Printf(\"--I-- NG, could not joined (%v) %v\\n\",rcode,stat)\n\t}\n}\nfunc (gsh*GshContext)Rexec(argv[]string){\n\tif len(argv) <= 1 {\n\t\tfmt.Printf(\"--I-- rexec command [ | {file || {command} ]\\n\",gsh.RSERV)\n\t\treturn\n\t}\n\n\t\/*\n\tnargv := gshScanArg(strings.Join(argv,\" \"),0)\n\tfmt.Printf(\"--D-- nargc=%d [%v]\\n\",len(nargv),nargv)\n\tif nargv[1][0] != '{' {\n\t\tnargv[1] = \"{\" + nargv[1] + \"}\"\n\t\tfmt.Printf(\"--D-- nargc=%d [%v]\\n\",len(nargv),nargv)\n\t}\n\targv = nargv\n\t*\/\n\tnargv := []string{}\n\tnargv = append(nargv,\"{\"+strings.Join(argv[1:],\" \")+\"}\")\n\tfmt.Printf(\"--D-- nargc=%d %v\\n\",len(nargv),nargv)\n\targv = nargv\n\n\txargv := []string{\"rex-exec\",\"@\"+gsh.RSERV,\"GET\"}\n\txargv = append(xargv,argv...)\n\txargv = append(xargv,\"\/dev\/tty\")\n\trcode,stat := gsh.RexecClient(xargv)\n\tif (rcode \/ 100) == 2 {\n\t\tfmt.Printf(\"--I-- OK Rexec (%v) %v\\n\",rcode,stat)\n\t}else{\n\t\tfmt.Printf(\"--I-- NG Rexec (%v) %v\\n\",rcode,stat)\n\t}\n}\nfunc (gsh*GshContext)Rchdir(argv[]string){\n\tif len(argv) <= 1 {\n\t\treturn\n\t}\n\tcwd, _ := os.Getwd()\n\tos.Chdir(gsh.RWD)\n\tos.Chdir(argv[1])\n\ttwd, _ := os.Getwd()\n\tgsh.RWD = twd\n\tfmt.Printf(\"--I-- JWD=%v\\n\",twd)\n\tos.Chdir(cwd)\n}\nfunc (gsh*GshContext)Rpwd(argv[]string){\n\tfmt.Printf(\"%v\\n\",gsh.RWD)\n}\nfunc (gsh*GshContext)Rls(argv[]string){\n\tcwd, _ := os.Getwd()\n\tos.Chdir(gsh.RWD)\n\targv[0] = \"-ls\"\n\tgsh.xFind(argv)\n\tos.Chdir(cwd)\n}\nfunc (gsh*GshContext)Rput(argv[]string){\n\tvar local string = \"\"\n\tvar remote string = \"\"\n\tif 1 < len(argv) {\n\t\tlocal = argv[1]\n\t\tremote = local \/\/ base name\n\t}\n\tif 2 < len(argv) {\n\t\tremote = argv[2]\n\t}\n\tfmt.Printf(\"--I-- jput from=%v to=%v\\n\",local,gsh.Trelpath(remote))\n}\nfunc (gsh*GshContext)Rget(argv[]string){\n\tvar remote string = \"\"\n\tvar local string = \"\"\n\tif 1 < len(argv) {\n\t\tremote = argv[1]\n\t\tlocal = remote \/\/ base name\n\t}\n\tif 2 < len(argv) {\n\t\tlocal = argv[2]\n\t}\n\tfmt.Printf(\"--I-- jget from=%v to=%v\\n\",gsh.Trelpath(remote),local)\n}\n\n\/\/ <a name=\"network\">network<\/a>\n\/\/ -s, -si, -so \/\/ bi-directional, source, sync (maybe socket)\nfunc (gshCtx*GshContext)sconnect(inTCP bool, argv []string) {\n\tgshPA := gshCtx.gshPA\n\tif len(argv) < 2 {\n\t\tfmt.Printf(\"Usage: -s [host]:[port[.udp]]\\n\")\n\t\treturn\n\t}\n\tremote := argv[1]\n\tif remote == \":\" { remote = \"0.0.0.0:9999\" }\n\n\tif inTCP { \/\/ TCP\n\t\tdport, err := net.ResolveTCPAddr(\"tcp\",remote);\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Address error: %s (%s)\\n\",remote,err)\n\t\t\treturn\n\t\t}\n\t\tconn, err := net.DialTCP(\"tcp\",nil,dport)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Connection error: %s (%s)\\n\",remote,err)\n\t\t\treturn\n\t\t}\n\t\tfile, _ := conn.File();\n\t\tfd := file.Fd()\n\t\tfmt.Printf(\"Socket: connected to %s, socket[%d]\\n\",remote,fd)\n\n\t\tsavfd := gshPA.Files[1]\n\t\tgshPA.Files[1] = fd;\n\t\tgshCtx.gshellv(argv[2:])\n\t\tgshPA.Files[1] = savfd\n\t\tfile.Close()\n\t\tconn.Close()\n\t}else{\n\t\t\/\/dport, err := net.ResolveUDPAddr(\"udp4\",remote);\n\t\tdport, err := net.ResolveUDPAddr(\"udp\",remote);\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Address error: %s (%s)\\n\",remote,err)\n\t\t\treturn\n\t\t}\n\t\t\/\/conn, err := net.DialUDP(\"udp4\",nil,dport)\n\t\tconn, err := net.DialUDP(\"udp\",nil,dport)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Connection error: %s (%s)\\n\",remote,err)\n\t\t\treturn\n\t\t}\n\t\tfile, _ := conn.File();\n\t\tfd := file.Fd()\n\n\t\tar := conn.RemoteAddr()\n\t\t\/\/al := conn.LocalAddr()\n\t\tfmt.Printf(\"Socket: connected to %s [%s], socket[%d]\\n\",\n\t\t\tremote,ar.String(),fd)\n\n\t\tsavfd := gshPA.Files[1]\n\t\tgshPA.Files[1] = fd;\n\t\tgshCtx.gshellv(argv[2:])\n\t\tgshPA.Files[1] = savfd\n\t\tfile.Close()\n\t\tconn.Close()\n\t}\n}\nfunc (gshCtx*GshContext)saccept(inTCP bool, argv []string) {\n\tgshPA := gshCtx.gshPA\n\tif len(argv) < 2 {\n\t\tfmt.Printf(\"Usage: -ac [host]:[port[.udp]]\\n\")\n\t\treturn\n\t}\n\tlocal := argv[1]\n\tif local == \":\" { local = \"0.0.0.0:9999\" }\n\tif inTCP { \/\/ TCP\n\t\tport, err := net.ResolveTCPAddr(\"tcp\",local);\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Address error: %s (%s)\\n\",local,err)\n\t\t\treturn\n\t\t}\n\t\t\/\/fmt.Printf(\"Listen at %s...\\n\",local);\n\t\tsconn, err := net.ListenTCP(\"tcp\", port)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Listen error: %s (%s)\\n\",local,err)\n\t\t\treturn\n\t\t}\n\t\t\/\/fmt.Printf(\"Accepting at %s...\\n\",local);\n\t\taconn, err := sconn.AcceptTCP()\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Accept error: %s (%s)\\n\",local,err)\n\t\t\treturn\n\t\t}\n\t\tfile, _ := aconn.File()\n\t\tfd := file.Fd()\n\t\tfmt.Printf(\"Accepted TCP at %s [%d]\\n\",local,fd)\n\n\t\tsavfd := gshPA.Files[0]\n\t\tgshPA.Files[0] = fd;\n\t\tgshCtx.gshellv(argv[2:])\n\t\tgshPA.Files[0] = savfd\n\n\t\tsconn.Close();\n\t\taconn.Close();\n\t\tfile.Close();\n\t}else{\n\t\t\/\/port, err := net.ResolveUDPAddr(\"udp4\",local);\n\t\tport, err := net.ResolveUDPAddr(\"udp\",local);\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Address error: %s (%s)\\n\",local,err)\n\t\t\treturn\n\t\t}\n\t\tfmt.Printf(\"Listen UDP at %s...\\n\",local);\n\t\t\/\/uconn, err := net.ListenUDP(\"udp4\", port)\n\t\tuconn, err := net.ListenUDP(\"udp\", port)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"Listen error: %s (%s)\\n\",local,err)\n\t\t\treturn\n\t\t}\n\t\tfile, _ := uconn.File()\n\t\tfd := file.Fd()\n\t\tar := uconn.RemoteAddr()\n\t\tremote := \"\"\n\t\tif ar != nil { remote = ar.String() }\n\t\tif remote == \"\" { remote = \"?\" }\n\n\t\t\/\/ not yet received\n\t\t\/\/fmt.Printf(\"Accepted at %s [%d] <- %s\\n\",local,fd,\"\")\n\n\t\tsavfd := gshPA.Files[0]\n\t\tgshPA.Files[0] = fd;\n\t\tsavenv := gshPA.Env\n\t\tgshPA.Env = append(savenv, \"REMOTE_HOST=\"+remote)\n\t\tgshCtx.gshellv(argv[2:])\n\t\tgshPA.Env = savenv\n\t\tgshPA.Files[0] = savfd\n\n\t\tuconn.Close();\n\t\tfile.Close();\n\t}\n}\n\n\/\/ empty line command\nfunc (gshCtx*GshContext)xPwd(argv[]string){\n\t\/\/ execute context command, pwd + date\n\t\/\/ context notation, representation scheme, to be resumed at re-login\n\tcwd, _ := os.Getwd()\n\tswitch {\n\tcase isin(\"-a\",argv):\n\t\tgshCtx.ShowChdirHistory(argv)\n\tcase isin(\"-ls\",argv):\n\t\tshowFileInfo(cwd,argv)\n\tdefault:\n\t\tfmt.Printf(\"%s\\n\",cwd)\n\tcase isin(\"-v\",argv): \/\/ obsolete emtpy command\n\t\tt := time.Now()\n\t\tdate := t.Format(time.UnixDate)\n\t\texe, _ := os.Executable()\n\t\thost, _ := os.Hostname()\n\t\tfmt.Printf(\"{PWD=\\\"%s\\\"\",cwd)\n\t\tfmt.Printf(\" HOST=\\\"%s\\\"\",host)\n\t\tfmt.Printf(\" DATE=\\\"%s\\\"\",date)\n\t\tfmt.Printf(\" TIME=\\\"%s\\\"\",t.String())\n\t\tfmt.Printf(\" PID=\\\"%d\\\"\",os.Getpid())\n\t\tfmt.Printf(\" EXE=\\\"%s\\\"\",exe)\n\t\tfmt.Printf(\"}\\n\")\n\t}\n}\n\n\/\/ <a name=\"history\">History<\/a>\n\/\/ these should be browsed and edited by HTTP browser\n\/\/ show the time of command with -t and direcotry with -ls\n\/\/ openfile-history, sort by -a -m -c\n\/\/ sort by elapsed time by -t -s\n\/\/ search by \"more\" like interface\n\/\/ edit history\n\/\/ sort history, and wc or uniq\n\/\/ CPU and other resource consumptions\n\/\/ limit showing range (by time or so)\n\/\/ export \/ import history\nfunc (gshCtx *GshContext)xHistory(argv []string){\n\tatWorkDirX := -1\n\tif 1 < len(argv) && strBegins(argv[1],\"@\") {\n\t\tatWorkDirX,_ = strconv.Atoi(argv[1][1:])\n\t}\n\t\/\/fmt.Printf(\"--D-- showHistory(%v)\\n\",argv)\n\tfor i, v := range gshCtx.CommandHistory {\n\t\t\/\/ exclude commands not to be listed by default\n\t\t\/\/ internal commands may be suppressed by default\n\t\tif v.CmdLine == \"\" && !isin(\"-a\",argv) {\n\t\t\tcontinue;\n\t\t}\n\t\tif 0 <= atWorkDirX {\n\t\t\tif v.WorkDirX != atWorkDirX {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif !isin(\"-n\",argv){ \/\/ like \"fc\"\n\t\t\tfmt.Printf(\"!%-2d \",i)\n\t\t}\n\t\tif isin(\"-v\",argv){\n\t\t\tfmt.Println(v) \/\/ should be with it date\n\t\t}else{\n\t\t\tif isin(\"-l\",argv) || isin(\"-l0\",argv) {\n\t\t\t\telps := v.EndAt.Sub(v.StartAt);\n\t\t\t\tstart := v.StartAt.Format(time.Stamp)\n\t\t\t\tfmt.Printf(\"@%d \",v.WorkDirX)\n\t\t\t\tfmt.Printf(\"[%v] %11v\/t \",start,elps)\n\t\t\t}\n\t\t\tif isin(\"-l\",argv) && !isin(\"-l0\",argv){\n\t\t\t\tfmt.Printf(\"%v\",Rusagef(\"%t %u\\t\/\/ %s\",argv,v.Rusagev))\n\t\t\t}\n\t\t\tif isin(\"-at\",argv) { \/\/ isin(\"-ls\",argv){\n\t\t\t\tdhi := v.WorkDirX \/\/ workdir history index\n\t\t\t\tfmt.Printf(\"@%d %s\\t\",dhi,v.WorkDir)\n\t\t\t\t\/\/ show the FileInfo of the output command??\n\t\t\t}\n\t\t\tfmt.Printf(\"%s\",v.CmdLine)\n\t\t\tfmt.Printf(\"\\n\")\n\t\t}\n\t}\n}\n\/\/ !n - history index\nfunc searchHistory(gshCtx GshContext, gline string) (string, bool, bool){\n\tif gline[0] == '!' {\n\t\thix, err := strconv.Atoi(gline[1:])\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"--E-- (%s : range)\\n\",hix)\n\t\t\treturn \"\", false, true\n\t\t}\n\t\tif hix < 0 || len(gshCtx.CommandHistory) <= hix {\n\t\t\tfmt.Printf(\"--E-- (%d : out of range)\\n\",hix)\n\t\t\treturn \"\", false, true\n\t\t}\n\t\treturn gshCtx.CommandHistory[hix].CmdLine, false, false\n\t}\n\t\/\/ search\n\t\/\/for i, v := range gshCtx.CommandHistory {\n\t\/\/}\n\treturn gline, false, false\n}\nfunc (gsh*GshContext)cmdStringInHistory(hix int)(cmd string, ok bool){\n\tif 0 <= hix && hix < len(gsh.CommandHistory) {\n\t\treturn gsh.CommandHistory[hix].CmdLine,true\n\t}\n\treturn \"\",false\n}\n\n\/\/ temporary adding to PATH environment\n\/\/ cd name -lib for LD_LIBRARY_PATH\n\/\/ chdir with directory history (date + full-path)\n\/\/ -s for sort option (by visit date or so)\nfunc (gsh*GshContext)ShowChdirHistory1(i int,v GChdirHistory, argv []string){\n\tfmt.Printf(\"!%-2d \",v.CmdIndex) \/\/ the first command at this WorkDir\n\tfmt.Printf(\"@%d \",i)\n\tfmt.Printf(\"[%v] \",v.MovedAt.Format(time.Stamp))\n\tshowFileInfo(v.Dir,argv)\n}\nfunc (gsh*GshContext)ShowChdirHistory(argv []string){\n\tfor i, v := range gsh.ChdirHistory {\n\t\tgsh.ShowChdirHistory1(i,v,argv)\n\t}\n}\nfunc skipOpts(argv[]string)(int){\n\tfor i,v := range argv {\n\t\tif strBegins(v,\"-\") {\n\t\t}else{\n\t\t\treturn i\n\t\t}\n\t}\n\treturn -1\n}\nfunc (gshCtx*GshContext)xChdir(argv []string){\n\tcdhist := gshCtx.ChdirHistory\n\tif isin(\"?\",argv ) || isin(\"-t\",argv) || isin(\"-a\",argv) {\n\t\tgshCtx.ShowChdirHistory(argv)\n\t\treturn\n\t}\n\tpwd, _ := os.Getwd()\n\tdir := \"\"\n\tif len(argv) <= 1 {\n\t\tdir = toFullpath(\"~\")\n\t}else{\n\t\ti := skipOpts(argv[1:])\n\t\tif i < 0 {\n\t\t\tdir = toFullpath(\"~\")\n\t\t}else{\n\t\t\tdir = argv[1+i]\n\t\t}\n\t}\n\tif strBegins(dir,\"@\") {\n\t\tif dir == \"@0\" { \/\/ obsolete\n\t\t\tdir = gshCtx.StartDir\n\t\t}else\n\t\tif dir == \"@!\" {\n\t\t\tindex := len(cdhist) - 1\n\t\t\tif 0 < index { index -= 1 }\n\t\t\tdir = cdhist[index].Dir\n\t\t}else{\n\t\t\tindex, err := strconv.Atoi(dir[1:])\n\t\t\tif err != nil {\n\t\t\t\tfmt.Printf(\"--E-- xChdir(%v)\\n\",err)\n\t\t\t\tdir = \"?\"\n\t\t\t}else\n\t\t\tif len(gshCtx.ChdirHistory) <= index {\n\t\t\t\tfmt.Printf(\"--E-- xChdir(history range error)\\n\")\n\t\t\t\tdir = \"?\"\n\t\t\t}else{\n\t\t\t\tdir = cdhist[index].Dir\n\t\t\t}\n\t\t}\n\t}\n\tif dir != \"?\" {\n\t\terr := os.Chdir(dir)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"--E-- xChdir(%s)(%v)\\n\",argv[1],err)\n\t\t}else{\n\t\t\tcwd, _ := os.Getwd()\n\t\t\tif cwd != pwd {\n\t\t\t\thist1 := GChdirHistory { }\n\t\t\t\thist1.Dir = cwd\n\t\t\t\thist1.MovedAt = time.Now()\n\t\t\t\thist1.CmdIndex = len(gshCtx.CommandHistory)+1\n\t\t\t\tgshCtx.ChdirHistory = append(cdhist,hist1)\n\t\t\t\tif !isin(\"-s\",argv){\n\t\t\t\t\t\/\/cwd, _ := os.Getwd()\n\t\t\t\t\t\/\/fmt.Printf(\"%s\\n\",cwd)\n\t\t\t\t\tix := len(gshCtx.ChdirHistory)-1\n\t\t\t\t\tgshCtx.ShowChdirHistory1(ix,hist1,argv)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif isin(\"-ls\",argv){\n\t\tcwd, _ := os.Getwd()\n\t\tshowFileInfo(cwd,argv);\n\t}\n}\nfunc TimeValSub(tv1 *syscall.Timeval, tv2 *syscall.Timeval){\n\t*tv1 = syscall.NsecToTimeval(tv1.Nano() - tv2.Nano())  \n}\nfunc RusageSubv(ru1, ru2 [2]syscall.Rusage)([2]syscall.Rusage){\n\tTimeValSub(&ru1[0].Utime,&ru2[0].Utime)\n\tTimeValSub(&ru1[0].Stime,&ru2[0].Stime)\n\tTimeValSub(&ru1[1].Utime,&ru2[1].Utime)\n\tTimeValSub(&ru1[1].Stime,&ru2[1].Stime)\n\treturn ru1\n}\nfunc TimeValAdd(tv1 syscall.Timeval, tv2 syscall.Timeval)(syscall.Timeval){\n\ttvs := syscall.NsecToTimeval(tv1.Nano() + tv2.Nano())  \n\treturn tvs\n}\n\/*\nfunc RusageAddv(ru1, ru2 [2]syscall.Rusage)([2]syscall.Rusage){\n\tTimeValAdd(ru1[0].Utime,ru2[0].Utime)\n\tTimeValAdd(ru1[0].Stime,ru2[0].Stime)\n\tTimeValAdd(ru1[1].Utime,ru2[1].Utime)\n\tTimeValAdd(ru1[1].Stime,ru2[1].Stime)\n\treturn ru1\n}\n*\/\n\n\/\/ <a name=\"rusage\">Resource Usage<\/a>\nfunc sRusagef(fmtspec string, argv []string, ru [2]syscall.Rusage)(string){\n\t\/\/ ru[0] self , ru[1] children\n\tut := TimeValAdd(ru[0].Utime,ru[1].Utime)\n\tst := TimeValAdd(ru[0].Stime,ru[1].Stime)\n\tuu := (ut.Sec*1000000 + int64(ut.Usec)) * 1000\n\tsu := (st.Sec*1000000 + int64(st.Usec)) * 1000\n\ttu := uu + su\n\tret := fmt.Sprintf(\"%v\/sum\",abbtime(tu))\n\tret += fmt.Sprintf(\", %v\/usr\",abbtime(uu))\n\tret += fmt.Sprintf(\", %v\/sys\",abbtime(su))\n\treturn ret\n}\nfunc Rusagef(fmtspec string, argv []string, ru [2]syscall.Rusage)(string){\n\tut := TimeValAdd(ru[0].Utime,ru[1].Utime)\n\tst := TimeValAdd(ru[0].Stime,ru[1].Stime)\n\tfmt.Printf(\"%d.%06ds\/u \",ut.Sec,ut.Usec) \/\/ru[1].Utime.Sec,ru[1].Utime.Usec)\n\tfmt.Printf(\"%d.%06ds\/s \",st.Sec,st.Usec) \/\/ru[1].Stime.Sec,ru[1].Stime.Usec)\n\treturn \"\"\n}\nfunc Getrusagev()([2]syscall.Rusage){\n\tvar ruv = [2]syscall.Rusage{}\n\tsyscall.Getrusage(syscall.RUSAGE_SELF,&ruv[0])\n\tsyscall.Getrusage(syscall.RUSAGE_CHILDREN,&ruv[1])\n\treturn ruv\n}\nfunc showRusage(what string,argv []string, ru *syscall.Rusage){\n\tfmt.Printf(\"%s: \",what);\n\tfmt.Printf(\"Usr=%d.%06ds\",ru.Utime.Sec,ru.Utime.Usec)\n\tfmt.Printf(\" Sys=%d.%06ds\",ru.Stime.Sec,ru.Stime.Usec)\n\tfmt.Printf(\" Rss=%vB\",ru.Maxrss)\n\tif isin(\"-l\",argv) {\n\t\tfmt.Printf(\" MinFlt=%v\",ru.Minflt)\n\t\tfmt.Printf(\" MajFlt=%v\",ru.Majflt)\n\t\tfmt.Printf(\" IxRSS=%vB\",ru.Ixrss)\n\t\tfmt.Printf(\" IdRSS=%vB\",ru.Idrss)\n\t\tfmt.Printf(\" Nswap=%vB\",ru.Nswap)\n\tfmt.Printf(\" Read=%v\",ru.Inblock)\n\tfmt.Printf(\" Write=%v\",ru.Oublock)\n\t}\n\tfmt.Printf(\" Snd=%v\",ru.Msgsnd)\n\tfmt.Printf(\" Rcv=%v\",ru.Msgrcv)\n\t\/\/if isin(\"-l\",argv) {\n\t\tfmt.Printf(\" Sig=%v\",ru.Nsignals)\n\t\/\/}\n\tfmt.Printf(\"\\n\");\n}\nfunc (gshCtx *GshContext)xTime(argv[]string)(bool){\n\tif 2 <= len(argv){\n\t\tgshCtx.LastRusage = syscall.Rusage{}\n\t\trusagev1 := Getrusagev()\n\t\tfin := gshCtx.gshellv(argv[1:])\n\t\trusagev2 := Getrusagev()\n\t\tshowRusage(argv[1],argv,&gshCtx.LastRusage)\n\t\trusagev := RusageSubv(rusagev2,rusagev1)\n\t\tshowRusage(\"self\",argv,&rusagev[0])\n\t\tshowRusage(\"chld\",argv,&rusagev[1])\n\t\treturn fin\n\t}else{\n\t\trusage:= syscall.Rusage {}\n\t\tsyscall.Getrusage(syscall.RUSAGE_SELF,&rusage)\n\t\tshowRusage(\"self\",argv, &rusage)\n\t\tsyscall.Getrusage(syscall.RUSAGE_CHILDREN,&rusage)\n\t\tshowRusage(\"chld\",argv, &rusage)\n\t\treturn false\n\t}\n}\nfunc (gshCtx *GshContext)xJobs(argv[]string){\n\tfmt.Printf(\"%d Jobs\\n\",len(gshCtx.BackGroundJobs))\n\tfor ji, pid := range gshCtx.BackGroundJobs {\n\t\t\/\/wstat := syscall.WaitStatus {0}\n\t\trusage := syscall.Rusage {}\n\t\t\/\/wpid, err := syscall.Wait4(pid,&wstat,syscall.WNOHANG,&rusage);\n\t\twpid, err := syscall.Wait4(pid,nil,syscall.WNOHANG,&rusage);\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"--E-- %%%d [%d] (%v)\\n\",ji,pid,err)\n\t\t}else{\n\t\t\tfmt.Printf(\"%%%d[%d](%d)\\n\",ji,pid,wpid)\n\t\t\tshowRusage(\"chld\",argv,&rusage)\n\t\t}\n\t}\n}\nfunc (gsh*GshContext)inBackground(argv[]string)(bool){\n\tif gsh.CmdTrace { fmt.Printf(\"--I-- inBackground(%v)\\n\",argv) }\n\tgsh.BackGround = true \/\/ set background option\n\txfin := false\n\txfin = gsh.gshellv(argv)\n\tgsh.BackGround = false\n\treturn xfin\n}\n\/\/ -o file without command means just opening it and refer by #N\n\/\/ should be listed by \"files\" comnmand\nfunc (gshCtx*GshContext)xOpen(argv[]string){\n\tvar pv = []int{-1,-1}\n\terr := syscall.Pipe(pv)\n\tfmt.Printf(\"--I-- pipe()=[#%d,#%d](%v)\\n\",pv[0],pv[1],err)\n}\nfunc (gshCtx*GshContext)fromPipe(argv[]string){\n}\nfunc (gshCtx*GshContext)xClose(argv[]string){\n}\n\n\/\/ <a name=\"redirect\">redirect<\/a>\nfunc (gshCtx*GshContext)redirect(argv[]string)(bool){\n\tif len(argv) < 2 {\n\t\treturn false\n\t}\n\n\tcmd := argv[0]\n\tfname := argv[1]\n\tvar file *os.File = nil\n\n\tfdix := 0\n\tmode := os.O_RDONLY\n\n\tswitch {\n\tcase cmd == \"-i\" || cmd == \"<\":\n\t\tfdix = 0\n\t\tmode = os.O_RDONLY\n\tcase cmd == \"-o\" || cmd == \">\":\n\t\tfdix = 1\n\t\tmode = os.O_RDWR | os.O_CREATE\n\tcase cmd == \"-a\" || cmd == \">>\":\n\t\tfdix = 1\n\t\tmode = os.O_RDWR | os.O_CREATE | os.O_APPEND\n\t}\n\tif fname[0] == '#' {\n\t\tfd, err := strconv.Atoi(fname[1:])\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"--E-- (%v)\\n\",err)\n\t\t\treturn false\n\t\t}\n\t\tfile = os.NewFile(uintptr(fd),\"MaybePipe\")\n\t}else{\n\t\txfile, err := os.OpenFile(argv[1], mode, 0600)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"--E-- (%s)\\n\",err)\n\t\t\treturn false\n\t\t}\n\t\tfile = xfile\n\t}\n\tgshPA := gshCtx.gshPA\n\tsavfd := gshPA.Files[fdix]\n\tgshPA.Files[fdix] = file.Fd()\n\tfmt.Printf(\"--I-- Opened [%d] %s\\n\",file.Fd(),argv[1])\n\tgshCtx.gshellv(argv[2:])\n\tgshPA.Files[fdix] = savfd\n\n\treturn false\n}\n\n\/\/fmt.Fprintf(res, \"GShell Status: %q\", html.EscapeString(req.URL.Path))\nfunc httpHandler(res http.ResponseWriter, req *http.Request){\n\tpath := req.URL.Path\n\tfmt.Printf(\"--I-- Got HTTP Request(%s)\\n\",path)\n\t{\n\t\tgshCtxBuf, _ :=  setupGshContext()\n\t\tgshCtx := &gshCtxBuf\n\t\tfmt.Printf(\"--I-- %s\\n\",path[1:])\n\t\tgshCtx.tgshelll(path[1:])\n\t}\n\tfmt.Fprintf(res, \"Hello(^-^)\/\\n%s\\n\",path)\n}\nfunc (gshCtx *GshContext) httpServer(argv []string){\n\thttp.HandleFunc(\"\/\", httpHandler)\n\taccport := \"localhost:9999\"\n\tfmt.Printf(\"--I-- HTTP Server Start at [%s]\\n\",accport)\n\thttp.ListenAndServe(accport,nil)\n}\nfunc (gshCtx *GshContext)xGo(argv[]string){\n\tgo gshCtx.gshellv(argv[1:]);\n}\nfunc (gshCtx *GshContext) xPs(argv[]string)(){\n}\n\n\/\/ <a name=\"plugin\">Plugin<\/a>\n\/\/ plugin [-ls [names]] to list plugins\n\/\/ Reference: <a href=\"https:\/\/golang.org\/src\/plugin\/\">plugin<\/a> source code\nfunc (gshCtx *GshContext) whichPlugin(name string,argv[]string)(pi *PluginInfo){\n\tpi = nil\t\n\tfor _,p := range gshCtx.PluginFuncs {\n\t\tif p.Name == name && pi == nil {\n\t\t\tpi = &p\n\t\t}\n\t\tif !isin(\"-s\",argv){\n\t\t\t\/\/fmt.Printf(\"%v %v \",i,p)\n\t\t\tif isin(\"-ls\",argv){\n\t\t\t\tshowFileInfo(p.Path,argv)\n\t\t\t}else{\n\t\t\t\tfmt.Printf(\"%s\\n\",p.Name)\n\t\t\t}\n\t\t}\n\t}\n\treturn pi\n}\nfunc (gshCtx *GshContext) xPlugin(argv[]string) (error) {\n\tif len(argv) == 0 || argv[0] == \"-ls\" {\n\t\tgshCtx.whichPlugin(\"\",argv)\n\t\treturn  nil\n\t}\n\tname := argv[0]\n\tPin := gshCtx.whichPlugin(name,[]string{\"-s\"})\n\tif Pin != nil {\n\t\tos.Args = argv \/\/ should be recovered?\n\t\tPin.Addr.(func())()\n\t\treturn nil\n\t}\n\tsofile := toFullpath(argv[0] + \".so\") \/\/ or find it by which($PATH)\n\n\tp, err := plugin.Open(sofile)\n\tif err != nil {\n\t\tfmt.Printf(\"--E-- plugin.Open(%s)(%v)\\n\",sofile,err)\n\t\treturn err\n\t}\n\tfname := \"Main\"\n\tf, err := p.Lookup(fname)\n\tif( err != nil ){\n\t\tfmt.Printf(\"--E-- plugin.Lookup(%s)(%v)\\n\",fname,err)\n\t\treturn err\n\t}\n\tpin := PluginInfo {p,f,name,sofile} \n\tgshCtx.PluginFuncs = append(gshCtx.PluginFuncs,pin)\n\tfmt.Printf(\"--I-- added (%d)\\n\",len(gshCtx.PluginFuncs))\n\n\t\/\/fmt.Printf(\"--I-- first call(%s:%s)%v\\n\",sofile,fname,argv)\n\tos.Args = argv\n\tf.(func())()\n\treturn err\n}\nfunc (gshCtx*GshContext)Args(argv[]string){\n\tfor i,v := range os.Args {\n\t\tfmt.Printf(\"[%v] %v\\n\",i,v)\n\t}\n}\nfunc (gshCtx *GshContext) showVersion(argv[]string){\n\tif isin(\"-l\",argv) {\n\t\tfmt.Printf(\"%v\/%v (%v)\",NAME,VERSION,DATE);\n\t}else{\n\t\tfmt.Printf(\"%v\",VERSION);\n\t}\n\tif isin(\"-a\",argv) {\n\t\tfmt.Printf(\" %s\",AUTHOR)\n\t}\n\tif !isin(\"-n\",argv) {\n\t\tfmt.Printf(\"\\n\")\n\t}\n}\n\n\/\/ <a name=\"scanf\">Scanf<\/a> \/\/ string decomposer\n\/\/ scanf [format] [input]\nfunc scanv(sstr string)(strv[]string){\n\tstrv = strings.Split(sstr,\" \")\n\treturn strv\n}\nfunc scanUntil(src,end string)(rstr string,leng int){\n\tidx := strings.Index(src,end)\n\tif 0 <= idx {\n\t\trstr = src[0:idx]\n\t\treturn rstr,idx+len(end)\n\t}\n\treturn src,0\n}\n\n\/\/ -bn -- display base-name part only \/\/ can be in some %fmt, for sed rewriting\nfunc (gsh*GshContext)printVal(fmts string, vstr string, optv[]string){\n\t\/\/vint,err := strconv.Atoi(vstr)\n\tvar ival int64 = 0\n\tn := 0\n\terr := error(nil)\n\tif strBegins(vstr,\"_\") {\n\t\tvx,_ := strconv.Atoi(vstr[1:])\n\t\tif vx < len(gsh.iValues) {\n\t\t\tvstr = gsh.iValues[vx]\n\t\t}else{\n\t\t}\n\t}\n\t\/\/ should use Eval()\n\tif strBegins(vstr,\"0x\") {\n\t\tn,err = fmt.Sscanf(vstr[2:],\"%x\",&ival)\n\t}else{\n\t\tn,err = fmt.Sscanf(vstr,\"%d\",&ival)\n\/\/fmt.Printf(\"--D-- n=%d err=(%v) {%s}=%v\\n\",n,err,vstr, ival)\n\t}\n\tif n == 1 && err == nil {\n\t\t\/\/fmt.Printf(\"--D-- formatn(%v) ival(%v)\\n\",fmts,ival)\n\t\tfmt.Printf(\"%\"+fmts,ival)\n\t}else{\n\t\tif isin(\"-bn\",optv){\n\t\t\tfmt.Printf(\"%\"+fmts,filepath.Base(vstr))\n\t\t}else{\n\t\t\tfmt.Printf(\"%\"+fmts,vstr)\n\t\t}\n\t}\n}\nfunc (gsh*GshContext)printfv(fmts,div string,argv[]string,optv[]string,list[]string){\n\t\/\/fmt.Printf(\"{%d}\",len(list))\n\t\/\/curfmt := \"v\"\n\toutlen := 0\n\tcurfmt := gsh.iFormat\n\n\tif 0 < len(fmts) {\n\t\tfor xi := 0; xi < len(fmts); xi++ {\n\t\t\tfch := fmts[xi]\n\t\t\tif fch == '%' {\n\t\t\t\tif xi+1 < len(fmts) {\n\t\t\t\t\tcurfmt = string(fmts[xi+1])\n gsh.iFormat = curfmt\n\t\t\t\t\txi += 1\n\tif xi+1 < len(fmts) && fmts[xi+1] == '(' {\n\t\tvals,leng := scanUntil(fmts[xi+2:],\")\")\n\t\t\/\/fmt.Printf(\"--D-- show fmt(%v) val(%v) next(%v)\\n\",curfmt,vals,leng)\n\t\tgsh.printVal(curfmt,vals,optv)\n\t\txi += 2+leng-1\n\t\toutlen += 1\n\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tif fch == '_' {\n\t\t\t\thi,leng := scanInt(fmts[xi+1:])\n\t\t\t\tif 0 < leng {\n\t\t\t\t\tif hi < len(gsh.iValues) {\n\t\t\t\t\t\tgsh.printVal(curfmt,gsh.iValues[hi],optv)\n\t\t\t\t\t\toutlen += 1 \/\/ should be the real length\n\t\t\t\t\t}else{\n\t\t\t\t\t\tfmt.Printf(\"((out-range))\")\n\t\t\t\t\t}\n\t\t\t\t\txi += leng\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfmt.Printf(\"%c\",fch)\n\t\t\toutlen += 1\n\t\t}\n\t}else{\n\t\t\/\/fmt.Printf(\"--D-- print {%s}\\n\")\n\t\tfor i,v := range list {\n\t\t\tif 0 < i {\n\t\t\t\tfmt.Printf(div)\n\t\t\t}\n\t\t\tgsh.printVal(curfmt,v,optv)\n\t\t\toutlen += 1\n\t\t}\n\t}\n\tif 0 < outlen {\n\t\tfmt.Printf(\"\\n\")\n\t}\n}\nfunc (gsh*GshContext)Scanv(argv[]string){\n\t\/\/fmt.Printf(\"--D-- Scanv(%v)\\n\",argv)\n\tif len(argv) == 1 {\n\t\treturn\n\t}\n\targv = argv[1:]\n\tfmts := \"\"\n\tif strBegins(argv[0],\"-F\") {\n\t\tfmts = argv[0]\n\t\tgsh.iDelimiter = fmts\n\t\targv = argv[1:]\n\t}\n\tinput := strings.Join(argv,\" \")\n\tif fmts == \"\" { \/\/ simple decomposition\n\t\tv := scanv(input)\n\t\tgsh.iValues = v\n\t\t\/\/fmt.Printf(\"%v\\n\",strings.Join(v,\",\"))\n\t}else{\n\t\tv := make([]string,8)\n\t\tn,err := fmt.Sscanf(input,fmts,&v[0],&v[1],&v[2],&v[3])\n\t\tfmt.Printf(\"--D-- Scanf ->(%v) n=%d err=(%v)\\n\",v,n,err)\n\t\tgsh.iValues = v\n\t}\n}\nfunc (gsh*GshContext)Printv(argv[]string){\n\tif false { \/\/@@U\n\t\tfmt.Printf(\"%v\\n\",strings.Join(argv[1:],\" \"))\n\t\treturn\n\t}\n\t\/\/fmt.Printf(\"--D-- Printv(%v)\\n\",argv)\n\t\/\/fmt.Printf(\"%v\\n\",strings.Join(gsh.iValues,\",\"))\n\tdiv := gsh.iDelimiter\n\tfmts := \"\"\n\targv = argv[1:]\n\tif 0 < len(argv) {\n\t\tif strBegins(argv[0],\"-F\") {\n\t\t\tdiv = argv[0][2:]\n\t\t\targv = argv[1:]\n\t\t}\n\t}\n\n\toptv := []string{}\n\tfor _,v := range argv {\n\t\tif strBegins(v,\"-\"){\n\t\t\toptv = append(optv,v)\n\t\t\targv = argv[1:]\n\t\t}else{\n\t\t\tbreak;\n\t\t}\n\t}\n\tif 0 < len(argv) {\n\t\tfmts = strings.Join(argv,\" \")\n\t}\n\tgsh.printfv(fmts,div,argv,optv,gsh.iValues)\n}\nfunc (gsh*GshContext)Basename(argv[]string){\n\tfor i,v := range gsh.iValues {\n\t\tgsh.iValues[i] = filepath.Base(v)\n\t}\n}\nfunc (gsh*GshContext)Sortv(argv[]string){\n\tsv := gsh.iValues\n\tsort.Slice(sv , func(i,j int) bool {\n\t\treturn sv[i] < sv[j]\n\t})\n}\nfunc (gsh*GshContext)Shiftv(argv[]string){\n\tvi := len(gsh.iValues)\n\tif 0 < vi {\n\t\tif isin(\"-r\",argv) {\n\t\t\ttop := gsh.iValues[0]\n\t\t\tgsh.iValues = append(gsh.iValues[1:],top)\n\t\t}else{\n\t\t\tgsh.iValues = gsh.iValues[1:]\n\t\t}\n\t}\n}\n\nfunc (gsh*GshContext)Enq(argv[]string){\n}\nfunc (gsh*GshContext)Deq(argv[]string){\n}\nfunc (gsh*GshContext)Push(argv[]string){\n\tgsh.iValStack = append(gsh.iValStack,argv[1:])\n\tfmt.Printf(\"depth=%d\\n\",len(gsh.iValStack))\n}\nfunc (gsh*GshContext)Dump(argv[]string){\n\tfor i,v := range gsh.iValStack {\n\t\tfmt.Printf(\"%d %v\\n\",i,v)\n\t}\n}\nfunc (gsh*GshContext)Pop(argv[]string){\n\tdepth := len(gsh.iValStack)\n\tif 0 < depth {\n\t\tv := gsh.iValStack[depth-1]\n\t\tif isin(\"-cat\",argv){\n\t\t\tgsh.iValues = append(gsh.iValues,v...)\n\t\t}else{\n\t\t\tgsh.iValues = v\n\t\t}\n\t\tgsh.iValStack = gsh.iValStack[0:depth-1]\n\t\tfmt.Printf(\"depth=%d %s\\n\",len(gsh.iValStack),gsh.iValues)\n\t}else{\n\t\tfmt.Printf(\"depth=%d\\n\",depth)\n\t}\n}\n\n\/\/ <a name=\"interpreter\">Command Interpreter<\/a>\nfunc (gshCtx*GshContext)gshellv(argv []string) (fin bool) {\n\tfin = false\n\n\tif gshCtx.CmdTrace { fmt.Fprintf(os.Stderr,\"--I-- gshellv((%d))\\n\",len(argv)) }\n\tif len(argv) <= 0 {\n\t\treturn false\n\t}\n\txargv := []string{}\n\tfor ai := 0; ai < len(argv); ai++ {\n\t\txargv = append(xargv,strsubst(gshCtx,argv[ai],false))\n\t}\n\targv = xargv\n\tif false {\n\t\tfor ai := 0; ai < len(argv); ai++ {\n\t\t\tfmt.Printf(\"[%d] %s [%d]%T\\n\",\n\t\t\t\tai,argv[ai],len(argv[ai]),argv[ai])\n\t\t}\n\t}\n\tcmd := argv[0]\n\tif gshCtx.CmdTrace { fmt.Fprintf(os.Stderr,\"--I-- gshellv(%d)%v\\n\",len(argv),argv) }\n\tswitch { \/\/ https:\/\/tour.golang.org\/flowcontrol\/11\n\tcase cmd == \"\":\n\t\tgshCtx.xPwd([]string{}); \/\/ emtpy command\n\tcase cmd == \"-x\":\n\t\tgshCtx.CmdTrace = ! gshCtx.CmdTrace\n\tcase cmd == \"-xt\":\n\t\tgshCtx.CmdTime = ! gshCtx.CmdTime\n\tcase cmd == \"-ot\":\n\t\tgshCtx.sconnect(true, argv)\n\tcase cmd == \"-ou\":\n\t\tgshCtx.sconnect(false, argv)\n\tcase cmd == \"-it\":\n\t\tgshCtx.saccept(true , argv)\n\tcase cmd == \"-iu\":\n\t\tgshCtx.saccept(false, argv)\n\tcase cmd == \"-i\" || cmd == \"<\" || cmd == \"-o\" || cmd == \">\" || cmd == \"-a\" || cmd == \">>\" || cmd == \"-s\" || cmd == \"><\":\n\t\tgshCtx.redirect(argv)\n\tcase cmd == \"|\":\n\t\tgshCtx.fromPipe(argv)\n\tcase cmd == \"args\":\n\t\tgshCtx.Args(argv)\n\tcase cmd == \"bg\" || cmd == \"-bg\":\n\t\trfin := gshCtx.inBackground(argv[1:])\n\t\treturn rfin\n\tcase cmd == \"-bn\":\n\t\tgshCtx.Basename(argv)\n\tcase cmd == \"call\":\n\t\t_,_ = gshCtx.excommand(false,argv[1:])\n\tcase cmd == \"cd\" || cmd == \"chdir\":\n\t\tgshCtx.xChdir(argv);\n\tcase cmd == \"-cksum\":\n\t\tgshCtx.xFind(argv)\n\tcase cmd == \"-sum\":\n\t\tgshCtx.xFind(argv)\n\tcase cmd == \"close\":\n\t\tgshCtx.xClose(argv)\n\tcase cmd == \"gcp\":\n\t\tgshCtx.FileCopy(argv)\n\tcase cmd == \"dec\" || cmd == \"decode\":\n\t\tgshCtx.Dec(argv)\n\tcase cmd == \"#define\":\n\tcase cmd == \"dump\":\n\t\tgshCtx.Dump(argv)\n\tcase cmd == \"echo\":\n\t\techo(argv,true)\n\tcase cmd == \"enc\" || cmd == \"encode\":\n\t\tgshCtx.Enc(argv)\n\tcase cmd == \"env\":\n\t\tenv(argv)\n\tcase cmd == \"eval\":\n\t\txEval(argv[1:],true)\n\tcase cmd == \"exec\":\n\t\t_,_ = gshCtx.excommand(true,argv[1:])\n\t\t\/\/ should not return here\n\tcase cmd == \"exit\" || cmd == \"quit\":\n\t\t\/\/ write Result code EXIT to 3>\n\t\treturn true\n\tcase cmd == \"fdls\":\n\t\t\/\/ dump the attributes of fds (of other process)\n\tcase cmd == \"-find\" || cmd == \"fin\" || cmd == \"ufind\" || cmd == \"uf\":\n\t\tgshCtx.xFind(argv[1:])\n\tcase cmd == \"fu\":\n\t\tgshCtx.xFind(argv[1:])\n\tcase cmd == \"fork\":\n\t\t\/\/ mainly for a server\n\tcase cmd == \"-gen\":\n\t\tgshCtx.gen(argv)\n\tcase cmd == \"-go\":\n\t\tgshCtx.xGo(argv)\n\tcase cmd == \"-grep\":\n\t\tgshCtx.xFind(argv)\n\tcase cmd == \"gdeq\":\n\t\tgshCtx.Deq(argv)\n\tcase cmd == \"genq\":\n\t\tgshCtx.Enq(argv)\n\tcase cmd == \"gpop\":\n\t\tgshCtx.Pop(argv)\n\tcase cmd == \"gpush\":\n\t\tgshCtx.Push(argv)\n\tcase cmd == \"history\" || cmd == \"hi\": \/\/ hi should be alias\n\t\tgshCtx.xHistory(argv)\n\tcase cmd == \"jobs\":\n\t\tgshCtx.xJobs(argv)\n\tcase cmd == \"lnsp\":\n\t\tgshCtx.SplitLine(argv)\n\tcase cmd == \"-ls\":\n\t\tgshCtx.xFind(argv)\n\tcase cmd == \"nop\":\n\t\t\/\/ do nothing\n\tcase cmd == \"pipe\":\n\t\tgshCtx.xOpen(argv)\n\tcase cmd == \"plug\" || cmd == \"plugin\" || cmd == \"pin\":\n\t\tgshCtx.xPlugin(argv[1:])\n\tcase cmd == \"print\" || cmd == \"-pr\":\n\t\t\/\/ output internal slice \/\/ also sprintf should be\n\t\tgshCtx.Printv(argv)\n\tcase cmd == \"ps\":\n\t\tgshCtx.xPs(argv)\n\tcase cmd == \"pstitle\":\n\t\t\/\/ to be gsh.title\n\tcase cmd == \"rexecd\" || cmd == \"rexd\":\n\t\tgshCtx.RexecServer(argv)\n\tcase cmd == \"rexec\" || cmd == \"rex\":\n\t\tgshCtx.RexecClient(argv)\n\tcase cmd == \"repeat\" || cmd == \"rep\": \/\/ repeat cond command\n\t\tgshCtx.repeat(argv)\n\tcase cmd == \"scan\":\n\t\t\/\/ scan input (or so in fscanf) to internal slice (like Files or map)\n\t\tgshCtx.Scanv(argv)\n\tcase cmd == \"set\":\n\t\t\/\/ set name ...\n\tcase cmd == \"serv\":\n\t\tgshCtx.httpServer(argv)\n\tcase cmd == \"shift\":\n\t\tgshCtx.Shiftv(argv)\n\tcase cmd == \"sleep\":\n\t\tgshCtx.sleep(argv)\n\tcase cmd == \"-sort\":\n\t\tgshCtx.Sortv(argv)\n\n\tcase cmd == \"j\" || cmd == \"join\":\n\t\tgshCtx.Rjoin(argv)\n\tcase cmd == \"a\" || cmd == \"alpa\":\n\t\tgshCtx.Rexec(argv)\n\tcase cmd == \"jcd\" || cmd == \"jchdir\":\n\t\tgshCtx.Rchdir(argv)\n\tcase cmd == \"jget\":\n\t\tgshCtx.Rget(argv)\n\tcase cmd == \"jls\":\n\t\tgshCtx.Rls(argv)\n\tcase cmd == \"jput\":\n\t\tgshCtx.Rput(argv)\n\tcase cmd == \"jpwd\":\n\t\tgshCtx.Rpwd(argv)\n\n\tcase cmd == \"time\":\n\t\tfin = gshCtx.xTime(argv)\n\tcase cmd == \"pwd\":\n\t\tgshCtx.xPwd(argv);\n\tcase cmd == \"ver\" || cmd == \"-ver\" || cmd == \"version\":\n\t\tgshCtx.showVersion(argv)\n\tcase cmd == \"where\":\n\t\t\/\/ data file or so?\n\tcase cmd == \"which\":\n\t\twhich(\"PATH\",argv);\n\tdefault:\n\t\tif gshCtx.whichPlugin(cmd,[]string{\"-s\"}) != nil {\n\t\t\tgshCtx.xPlugin(argv)\n\t\t}else{\n\t\t\tnotfound,_ := gshCtx.excommand(false,argv)\n\t\t\tif notfound {\n\t\t\t\tfmt.Printf(\"--E-- command not found (%v)\\n\",cmd)\n\t\t\t}\n\t\t}\n\t}\n\treturn fin\n}\n\nfunc (gsh*GshContext)gshelll(gline string) (rfin bool) {\n\targv := strings.Split(string(gline),\" \")\n\tfin := gsh.gshellv(argv)\n\treturn fin\n}\nfunc (gsh*GshContext)tgshelll(gline string)(xfin bool){\n\tstart := time.Now()\n\tfin := gsh.gshelll(gline)\n\tend := time.Now()\n\telps := end.Sub(start);\n\tif gsh.CmdTime {\n\t\tfmt.Printf(\"--T-- \" + time.Now().Format(time.Stamp) + \"(%d.%09ds)\\n\",\n\t\t\telps\/1000000000,elps%1000000000)\n\t}\n\treturn fin\n}\nfunc Ttyid() (int) {\n\tfi, err := os.Stdin.Stat()\n\tif err != nil {\n\t\treturn 0;\n\t}\n\t\/\/fmt.Printf(\"Stdin: %v Dev=%d\\n\",\n\t\/\/\tfi.Mode(),fi.Mode()&os.ModeDevice)\n\tif (fi.Mode() & os.ModeDevice) != 0 {\n\t\tstat := syscall.Stat_t{};\n\t\terr := syscall.Fstat(0,&stat)\n\t\tif err != nil {\n\t\t\t\/\/fmt.Printf(\"--I-- Stdin: (%v)\\n\",err)\n\t\t}else{\n\t\t\t\/\/fmt.Printf(\"--I-- Stdin: rdev=%d %d\\n\",\n\t\t\t\/\/\tstat.Rdev&0xFF,stat.Rdev);\n\t\t\t\/\/fmt.Printf(\"--I-- Stdin: tty%d\\n\",stat.Rdev&0xFF);\n\t\t\treturn int(stat.Rdev & 0xFF)\n\t\t}\n\t}\n\treturn 0\n}\nfunc (gshCtx *GshContext) ttyfile() string {\n\t\/\/fmt.Printf(\"--I-- GSH_HOME=%s\\n\",gshCtx.GshHomeDir)\n\tttyfile := gshCtx.GshHomeDir + \"\/\" + \"gsh-tty\" +\n\t\t fmt.Sprintf(\"%02d\",gshCtx.TerminalId)\n\t\t \/\/strconv.Itoa(gshCtx.TerminalId)\n\t\/\/fmt.Printf(\"--I-- ttyfile=%s\\n\",ttyfile)\n\treturn ttyfile\n}\nfunc (gshCtx *GshContext) ttyline()(*os.File){\n\tfile, err := os.OpenFile(gshCtx.ttyfile(),os.O_RDWR|os.O_CREATE|os.O_TRUNC,0600)\n\tif err != nil {\n\t\tfmt.Printf(\"--F-- cannot open %s (%s)\\n\",gshCtx.ttyfile(),err)\n\t\treturn file;\n\t}\n\treturn file\n}\nfunc (gshCtx *GshContext)getline(hix int, skipping bool, prevline string) (string) {\n\tif( skipping ){\n\t\treader := bufio.NewReaderSize(os.Stdin,LINESIZE)\n\t\tline, _, _ := reader.ReadLine()\n\t\treturn string(line)\n\t}else\n\tif true {\n\t\treturn xgetline(hix,prevline,gshCtx)\n\t}\n\t\/*\n\telse\n\tif( with_exgetline && gshCtx.GetLine != \"\" ){\n\t\t\/\/var xhix int64 = int64(hix); \/\/ cast\n\t\tnewenv := os.Environ()\n\t\tnewenv = append(newenv, \"GSH_LINENO=\"+strconv.FormatInt(int64(hix),10) )\n\n\t\ttty := gshCtx.ttyline()\n\t\ttty.WriteString(prevline)\n\t\tPa := os.ProcAttr {\n\t\t\t\"\", \/\/ start dir\n\t\t\tnewenv, \/\/os.Environ(),\n\t\t\t[]*os.File{os.Stdin,os.Stdout,os.Stderr,tty},\n\t\t\tnil,\n\t\t}\n\/\/fmt.Printf(\"--I-- getline=%s \/\/ %s\\n\",gsh_getlinev[0],gshCtx.GetLine)\nproc, err := os.StartProcess(gsh_getlinev[0],[]string{\"getline\",\"getline\"},&Pa)\n\t\tif err != nil {\n\t\t\tfmt.Printf(\"--F-- getline process error (%v)\\n\",err)\n\t\t\t\/\/ for ; ; { }\n\t\t\treturn \"exit (getline program failed)\"\n\t\t}\n\t\t\/\/stat, err := proc.Wait()\n\t\tproc.Wait()\n\t\tbuff := make([]byte,LINESIZE)\n\t\tcount, err := tty.Read(buff)\n\t\t\/\/_, err = tty.Read(buff)\n\t\t\/\/fmt.Printf(\"--D-- getline (%d)\\n\",count)\n\t\tif err != nil {\n\t\t\tif ! (count == 0) { \/\/ && err.String() == \"EOF\" ) {\n\t\t\t\tfmt.Printf(\"--E-- getline error (%s)\\n\",err)\n\t\t\t}\n\t\t}else{\n\t\t\t\/\/fmt.Printf(\"--I-- getline OK \\\"%s\\\"\\n\",buff)\n\t\t}\n\t\ttty.Close()\n\t\tgline := string(buff[0:count])\n\t\treturn gline\n\t}else\n\t*\/\n\t{\n\t\t\/\/ if isatty {\n\t\t\tfmt.Printf(\"!%d\",hix)\n\t\t\tfmt.Print(PROMPT)\n\t\t\/\/ }\n\t\treader := bufio.NewReaderSize(os.Stdin,LINESIZE)\n\t\tline, _, _ := reader.ReadLine()\n\t\treturn string(line)\n\t}\n}\n\n\/\/== begin ======================================================= getline\n\/*\n * getline.c\n * 2020-0819 extracted from dog.c\n * getline.go\n * 2020-0822 ported to Go\n *\/\n\/*\npackage main \/\/ getline main\nimport (\n\t\"fmt\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/fmt\/\">fmt<\/a>\n\t\"strings\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/strings\/\">strings<\/a>\n\t\"os\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/os\/\">os<\/a>\n\t\"syscall\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/syscall\/\">syscall<\/a>\n\t\/\/\"bytes\"\t\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/os\/\">os<\/a>\n\t\/\/\"os\/exec\"\t\/\/ <a href=\"https:\/\/golang.org\/pkg\/os\/\">os<\/a>\n)\n*\/\n\n\/\/ C language compatibility functions\nvar errno = 0\nvar stdin  *os.File = os.Stdin\nvar stdout *os.File = os.Stdout\nvar stderr *os.File = os.Stderr\nvar EOF = -1\nvar NULL = 0\ntype FILE os.File\ntype StrBuff []byte\nvar NULL_FP *os.File = nil\nvar NULLSP = 0\n\/\/var LINESIZE = 1024\n\nfunc system(cmdstr string)(int){\n\tPA := syscall.ProcAttr {\n\t\t\"\", \/\/ the starting directory\n\t\tos.Environ(),\n\t\t[]uintptr{os.Stdin.Fd(),os.Stdout.Fd(),os.Stderr.Fd()},\n\t\tnil,\n\t}\n\targv := strings.Split(cmdstr,\" \")\n\tpid,err := syscall.ForkExec(argv[0],argv,&PA)\n\tif( err != nil ){\n\t\tfmt.Printf(\"--E-- syscall(%v) err(%v)\\n\",cmdstr,err)\n\t}\n\tsyscall.Wait4(pid,nil,0,nil)\n\n\t\/*\n\targv := strings.Split(cmdstr,\" \")\n\tfmt.Fprintf(os.Stderr,\"--I-- system(%v)\\n\",argv)\n\t\/\/cmd := exec.Command(argv[0:]...)\n\tcmd := exec.Command(argv[0],argv[1],argv[2])\n\tcmd.Stdin = strings.NewReader(\"output of system\")\n\tvar out bytes.Buffer\n\tcmd.Stdout = &out\n\tvar serr bytes.Buffer\n\tcmd.Stderr = &serr\n\terr := cmd.Run()\n\tif err != nil {\n\t\tfmt.Fprintf(os.Stderr,\"--E-- system(%v)err(%v)\\n\",argv,err)\n\t\tfmt.Printf(\"ERR:%s\\n\",serr.String())\n\t}else{\n\t\tfmt.Printf(\"%s\",out.String())\n\t}\n\t*\/\n\treturn 0\n}\nfunc atoi(str string)(ret int){\n\tret,err := fmt.Sscanf(str,\"%d\",ret)\n\tif err == nil {\n\t\treturn ret\n\t}else{\n\t\t\/\/ should set errno\n\t\treturn 0\n\t}\n}\nfunc getenv(name string)(string){\n\tval,got := os.LookupEnv(name)\n\tif got {\n\t\treturn val\n\t}else{\n\t\treturn \"?\"\n\t}\n}\nfunc strcpy(dst StrBuff, src string){\n\tvar i int\n\tsrcb := []byte(src)\n\tfor i = 0; i < len(src) && srcb[i] != 0; i++ {\n\t\tdst[i] = srcb[i]\n\t}\n\tdst[i] = 0\n}\nfunc xstrcpy(dst StrBuff, src StrBuff){\n\tdst = src\n}\nfunc strcat(dst StrBuff, src StrBuff){\n\tdst = append(dst,src...)\n}\nfunc strdup(str StrBuff)(string){\n\treturn string(str[0:strlen(str)])\n}\nfunc sstrlen(str string)(int){\n\treturn len(str)\n}\nfunc strlen(str StrBuff)(int){\n\tvar i int\n\tfor i = 0; i < len(str) && str[i] != 0; i++ {\n\t}\n\treturn i\n}\nfunc sizeof(data StrBuff)(int){\n\treturn len(data)\n}\nfunc isatty(fd int)(ret int){\n\treturn 1\n}\n\nfunc fopen(file string,mode string)(fp*os.File){\n\tif mode == \"r\" {\n\t\tfp,err := os.Open(file)\n\t\tif( err != nil ){\n\t\t\tfmt.Printf(\"--E-- fopen(%s,%s)=(%v)\\n\",file,mode,err)\n\t\t\treturn NULL_FP;\n\t\t}\n\t\treturn fp;\n\t}else{\n\t\tfp,err := os.OpenFile(file,os.O_RDWR|os.O_CREATE|os.O_TRUNC,0600)\n\t\tif( err != nil ){\n\t\t\treturn NULL_FP;\n\t\t}\n\t\treturn fp;\n\t}\n}\nfunc fclose(fp*os.File){\n\tfp.Close()\n}\nfunc fflush(fp *os.File)(int){\n\treturn 0\n}\nfunc fgetc(fp*os.File)(int){\n\tvar buf [1]byte\n\t_,err := fp.Read(buf[0:1])\n\tif( err != nil ){\n\t\treturn EOF;\n\t}else{\n\t\treturn int(buf[0])\n\t}\n}\nfunc sfgets(str*string, size int, fp*os.File)(int){\n\tbuf := make(StrBuff,size)\n\tvar ch int\n\tvar i int\n\tfor i = 0; i < len(buf)-1; i++ {\n\t\tch = fgetc(fp)\n\t\t\/\/fprintf(stderr,\"--fgets %d\/%d %X\\n\",i,len(buf),ch)\n\t\tif( ch == EOF ){\n\t\t\tbreak;\n\t\t}\n\t\tbuf[i] = byte(ch);\n\t\tif( ch == '\\n' ){\n\t\t\tbreak;\n\t\t}\n\t}\n\tbuf[i] = 0\n\t\/\/fprintf(stderr,\"--fgets %d\/%d (%s)\\n\",i,len(buf),buf[0:i])\n\treturn i\n}\nfunc fgets(buf StrBuff, size int, fp*os.File)(int){\n\tvar ch int\n\tvar i int\n\tfor i = 0; i < len(buf)-1; i++ {\n\t\tch = fgetc(fp)\n\t\t\/\/fprintf(stderr,\"--fgets %d\/%d %X\\n\",i,len(buf),ch)\n\t\tif( ch == EOF ){\n\t\t\tbreak;\n\t\t}\n\t\tbuf[i] = byte(ch);\n\t\tif( ch == '\\n' ){\n\t\t\tbreak;\n\t\t}\n\t}\n\tbuf[i] = 0\n\t\/\/fprintf(stderr,\"--fgets %d\/%d (%s)\\n\",i,len(buf),buf[0:i])\n\treturn i\n}\nfunc fputc(ch int , fp*os.File)(int){\n\tvar buf [1]byte\n\tbuf[0] = byte(ch)\n\tfp.Write(buf[0:1])\n\treturn 0\n}\nfunc fputs(buf StrBuff, fp*os.File)(int){\n\tfp.Write(buf)\n\treturn 0\n}\nfunc xfputss(str string, fp*os.File)(int){\n\treturn fputs([]byte(str),fp)\n}\nfunc sscanf(str StrBuff,fmts string, params ...interface{})(int){\n\tfmt.Sscanf(string(str[0:strlen(str)]),fmts,params...)\n\treturn 0\n}\nfunc fprintf(fp*os.File,fmts string, params ...interface{})(int){\n\tfmt.Fprintf(fp,fmts,params...)\n\treturn 0\n}\n\n\/\/ <a name=\"IME\">Command Line IME<\/a>\n\/\/----------------------------------------------------------------------- MyIME\nvar MyIMEVER = \"MyIME\/0.0.2\";\ntype RomKana struct {\n\tpat string;\n\tout string;\n}\nvar dicents = 0\nvar romkana [1024]RomKana\nfunc readDic()(int){\n\tvar rk *os.File;\n\tvar dic = \"MyIME-dic.txt\";\n\t\/\/rk = fopen(\"romkana.txt\",\"r\");\n\t\/\/rk = fopen(\"JK-JA-morse-dic.txt\",\"r\");\n\trk = fopen(dic,\"r\");\n\tif( rk == NULL_FP ){\n\t\tif( true ){\n\t\t\tfprintf(stderr,\"--%s-- Could not load %s\\n\",MyIMEVER,dic);\n\t\t}\n\t\treturn -1;\n\t}\n\tif( true ){\n\t\tvar di int;\n\t\tvar line = make(StrBuff,1024);\n\t\tvar pat string\n\t\tvar out string\n\t\tfor di = 0; di < 1024; di++ {\n\t\t\tif( fgets(line,sizeof(line),rk) == NULLSP ){\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tfmt.Sscanf(string(line[0:strlen(line)]),\"%s %s\",&pat,&out);\n\t\t\t\/\/sscanf(line,\"%s %[^\\r\\n]\",&pat,&out);\n\t\t\tromkana[di].pat = pat;\n\t\t\tromkana[di].out = out;\n\t\t\t\/\/fprintf(stderr,\"--Dd- %-10s %s\\n\",pat,out)\n\t\t}\n\t\tdicents += di\n\t\tif( false ){\n\t\t\tfprintf(stderr,\"--%s-- loaded romkana.txt [%d]\\n\",MyIMEVER,di);\n\t\t\tfor di = 0; di < dicents; di++ {\n\t\t\t\tfprintf(stderr,\n\t\t\t\t\t\"%s %s\\n\",romkana[di].pat,romkana[di].out);\n\t\t\t}\n\t\t}\n\t}\n\tfclose(rk);\n\n\t\/\/romkana[dicents].pat = \"\/\/ddump\"\n\t\/\/romkana[dicents].pat = \"\/\/ddump\" \/\/ dump the dic. and clean the command input\n\treturn 0;\n}\nfunc matchlen(stri string, pati string)(int){\n\tif strBegins(stri,pati) {\n\t\treturn len(pati)\n\t}else{\n\t\treturn 0\n\t}\n}\nfunc convs(src string)(string){\n\tvar si int;\n\tvar sx = len(src);\n\tvar di int;\n\tvar mi int;\n\tvar dstb []byte\n\n\tfor si = 0; si < sx; { \/\/ search max. match from the position \n\t\tif strBegins(src[si:],\"%x\/\") {\n\t\t\t\/\/ %x\/integer\/ \/\/ s\/a\/b\/\n\t\t\tix := strings.Index(src[si+3:],\"\/\")\n\t\t\tif 0 < ix {\n\t\t\t\tvar iv int = 0\n\t\t\t\t\/\/fmt.Sscanf(src[si+3:si+3+ix],\"%d\",&iv)\n\t\t\t\tfmt.Sscanf(src[si+3:si+3+ix],\"%v\",&iv)\n\t\t\t\tsval := fmt.Sprintf(\"%x\",iv)\n\t\t\t\tbval := []byte(sval)\n\t\t\t\tdstb = append(dstb,bval...)\n\t\t\t\tsi = si+3+ix+1\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tif strBegins(src[si:],\"%d\/\") {\n\t\t\t\/\/ %d\/integer\/ \/\/ s\/a\/b\/\n\t\t\tix := strings.Index(src[si+3:],\"\/\")\n\t\t\tif 0 < ix {\n\t\t\t\tvar iv int = 0\n\t\t\t\tfmt.Sscanf(src[si+3:si+3+ix],\"%v\",&iv)\n\t\t\t\tsval := fmt.Sprintf(\"%d\",iv)\n\t\t\t\tbval := []byte(sval)\n\t\t\t\tdstb = append(dstb,bval...)\n\t\t\t\tsi = si+3+ix+1\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tvar maxlen int = 0;\n\t\tvar len int;\n\t\tmi = -1;\n\t\tfor di = 0; di < dicents; di++ {\n\t\t\tlen = matchlen(src[si:],romkana[di].pat);\n\t\t\tif( maxlen < len ){\n\t\t\t\tmaxlen = len;\n\t\t\t\tmi = di;\n\t\t\t}\n\t\t}\n\t\tif( 0 < maxlen ){\n\t\t\tout := romkana[mi].out;\n\t\t\tdstb = append(dstb,[]byte(out)...);\n\t\t\tsi += maxlen;\n\t\t}else{\n\t\t\tdstb = append(dstb,src[si])\n\t\t\tsi += 1;\n\t\t}\n\t}\n\treturn string(dstb)\n}\nfunc trans(src string)(int){\n\tdst := convs(src);\n\txfputss(dst,stderr);\n\treturn 0;\n}\n\n\/\/------------------------------------------------------------- LINEEDIT\n\/\/ \"?\" at the top of the line means searching history\n\nvar GO_UP = 201\nvar GO_DOWN = 202\nvar GO_RIGHT = 203\nvar GO_LEFT = 204\n\nfunc getesc(in *os.File)(int){\n\tvar ch1 int\n\tvar ch2 int\n\tch1 = fgetc(in);\n\tch2 = fgetc(in);\n\tif false {\n\t\tfprintf(stderr,\"(%c\/%X %c\/%X)\",ch1,ch1,ch2,ch2);\n\t}\n\tswitch( ch1 ){\n\t\tcase '[':\n\t\t\tswitch( ch2 ){\n\t\t\t\tcase 'A': return GO_UP; \/\/ ^\n\t\t\t\tcase 'B': return GO_DOWN; \/\/ v\n\t\t\t\tcase 'C': return GO_RIGHT; \/\/ >\n\t\t\t\tcase 'D': return GO_LEFT; \/\/ <\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn 0;\n}\nfunc clearline(){\n\tvar i int\n\tfprintf(stderr,\"\\r\");\n\tfor i = 0; i < 80; i++ {\n\t\tfputc(' ',os.Stderr);\n\t}\n\tfprintf(stderr,\"\\r\");\n}\nvar romkanmode bool;\nvar insertmode int;\nfunc redraw(lno int,line string,right string){\n\tvar bsi int\n\tvar rlen int\n\tvar romkanmark string\n\n\tif( romkanmode ){\n\t\t\/\/romkanmark = \" *\";\n\t}else{\n\t\tromkanmark = \"\";\n\t}\n\tclearline();\n\txfputss(\"\\r\",stderr);\n\tif( romkanmode ){\n\t\tfprintf(stderr,\"[\\343\\201\\202r]\");\n\t\t\/\/fprintf(stderr,\"[R]\");\n\t}\n\tfprintf(stderr,\"!%d! \",lno);\n\tif( romkanmode ){\n\t\ttrans(line);\n\t\t\/\/fputs(romkanmark,stderr);\n\t\ttrans(right);\n\t}else{\n\t\txfputss(line,stderr);\n\t\t\/\/fputs(romkanmark,stderr);\n\t\txfputss(right,stderr);\n\t}\n\tif true { \/\/romkanmode {\n\t\tfprintf(stderr,\"\\r\")\n\t\tif romkanmode {\n\t\t\tfprintf(stderr,\"[\\343\\201\\202r]\");\n\t\t\tfprintf(stderr,\"!%d! \",lno);\n\t\t\ttrans(line);\n\t\t}else{\n\t\t\tfprintf(stderr,\"!%d! \",lno);\n\t\t\txfputss(line,stderr);\n\t\t}\n\t}else{\n\t\trlen = len(right) + len(romkanmark);\n\t\tif true {\n\t\t\tfor bsi = 0; bsi < rlen; bsi++ {\n\t\t\t\tfputc('\\b',stderr);\n\t\t\t}\n\t\t}\n\t}\n}\nfunc delHeadChar(str string)(rline string,head string){\n\t_,clen := utf8.DecodeRune([]byte(str))\n\thead = string(str[0:clen])\n\treturn str[clen:],head\n}\nfunc delTailChar(str string)(rline string, last string){\n\tvar i = 0\n\tvar clen = 0\n\tfor {\n\t\t_,siz := utf8.DecodeRune([]byte(str)[i:])\n\t\tif siz <= 0 { break }\n\t\tclen = siz\n\t\ti += siz\n\t}\n\tlast = str[len(str)-clen:]\n\treturn str[0:len(str)-clen],last\n}\n\n\/\/ 3> for output and history\n\/\/ 4> for keylog?\n\/\/ <a name=\"getline\">Command Line Editor<\/a>\nfunc xgetline(lno int, prevline string, gsh*GshContext)(string){\n\tlastlno := lno;\n\tline := \"\"\n\tright := \"\"\n\n\t\/\/readDic();\n\tif( isatty(0) == 0 ){\n\t\tif( sfgets(&line,LINESIZE,stdin) == NULL ){\n\t\t\tline = \"exit\\n\";\n\t\t}else{\n\t\t}\n\t\tgoto EXIT_GOT;\n\t}\n\tif( true ){\n\t\t\/\/var pts string;\n\t\t\/\/pts = ptsname(0);\n\t\t\/\/pts = ttyname(0);\n\t\t\/\/fprintf(stderr,\"--pts[0] = %s\\n\",pts?pts:\"?\");\n\t}\n\tif( false ){\n\t\tfprintf(stderr,\"! \");\n\t\tfflush(stderr);\n\t\tsfgets(&line,LINESIZE,stdin);\n\t}else{\n\t\tvar ch int;\n\n\t\tsystem(\"\/bin\/stty -echo -icanon\");\n\t\tredraw(lno,line,right);\n\t\tline = \"\"\n\t\tright = \"\"\n\t\tpch := -1\n\t\tfor {\n\t\t\tif( pch != -1 ){\n\t\t\t\tch = pch\n\t\t\t\tpch = -1\n\t\t\t}else{\n\t\t\t\tch = fgetc(stdin);\n\t\t\t}\n\t\t\tif( ch == 033 ){\n\t\t\t\tch = getesc(stdin);\n\t\t\t}\n\t\t\tif( ch == '\\\\' ){\n\t\t\t\tfputc(ch,stderr)\n\t\t\t\tch = fgetc(stdin)\n\t\t\t\tif( ch == 'j' || ch == 'J' ){\n\t\t\t\t\treadDic();\n\t\t\t\t\tromkanmode = !romkanmode;\n\t\t\t\t\tif( ch == 'J' ){\n\t\t\t\t\t\tfprintf(stderr,\"J\\r\\n\");\n\t\t\t\t\t}\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue\n\t\t\t\t}else\n\t\t\t\tif( ch == 'i' || ch == 'I' ){\n\t\t\t\t\tdst := convs(line+right);\n\t\t\t\t\tline = dst\n\t\t\t\t\tright = \"\"\n\t\t\t\t\tif( ch == 'I' ){\n\t\t\t\t\t\tfprintf(stderr,\"I\\r\\n\");\n\t\t\t\t\t}\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue\n\t\t\t\t}else{\n\t\t\t\t\tpch = ch\n\t\t\t\t\tch = '\\\\'\n\t\t\t\t}\n\t\t\t} \n\t\t\tswitch( ch ){\n\t\t\t\tcase 0:\n\t\t\t\t\tcontinue;\n\t\t\t\tcase GO_UP:\n\t\t\t\t\tif lno == 1 {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tcmd,ok := gsh.cmdStringInHistory(lno-1)\n\t\t\t\t\tif ok {\n\t\t\t\t\t\tline = cmd\n\t\t\t\t\t\tright = \"\"\n\t\t\t\t\t\tlno = lno - 1\n\t\t\t\t\t}\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue\n\t\t\t\tcase GO_DOWN:\n\t\t\t\t\tcmd,ok := gsh.cmdStringInHistory(lno+1)\n\t\t\t\t\tif ok {\n\t\t\t\t\t\tline = cmd\n\t\t\t\t\t\tright = \"\"\n\t\t\t\t\t\tlno = lno + 1\n\t\t\t\t\t}else{\n\t\t\t\t\t\tline = \"\"\n\t\t\t\t\t\tright = \"\"\n\t\t\t\t\t\tif lno == lastlno-1 {\n\t\t\t\t\t\t\tlno = lno + 1\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue\n\t\t\t\tcase GO_LEFT:\n\t\t\t\t\tif 0 < len(line) {\n\t\t\t\t\t\txline,tail := delTailChar(line)\n\t\t\t\t\t\tline = xline\n\t\t\t\t\t\tright = tail + right\n\t\t\t\t\t}\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue;\n\t\t\t\tcase GO_RIGHT:\n\t\t\t\t\tif( 0 < len(right) && right[0] != 0 ){\n\t\t\t\t\t\txright,head := delHeadChar(right)\n\t\t\t\t\t\tright = xright\n\t\t\t\t\t\tline += head\n\t\t\t\t\t}\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue;\n\t\t\t\tcase EOF:\n\t\t\t\t\tgoto EXIT;\n\t\t\t\tcase 'R'-0x40: \/\/ replace\n\t\t\t\t\tdst := convs(line+right);\n\t\t\t\t\tline = dst\n\t\t\t\t\tright = \"\"\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue;\n\t\t\t\tcase 'T'-0x40: \/\/ just show the result\n\t\t\t\t\treadDic();\n\t\t\t\t\tromkanmode = !romkanmode;\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue;\n\t\t\t\tcase 'L'-0x40:\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue\n\t\t\t\tcase 'K'-0x40:\n\t\t\t\t\tright = \"\"\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue\n\t\t\t\tcase 'E'-0x40:\n\t\t\t\t\tline += right\n\t\t\t\t\tright = \"\"\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue\n\t\t\t\tcase 'A'-0x40:\n\t\t\t\t\tright = line + right\n\t\t\t\t\tline = \"\"\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue\n\t\t\t\tcase 'U'-0x40:\n\t\t\t\t\tline = \"\"\n\t\t\t\t\tright = \"\"\n\t\t\t\t\tclearline();\n\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\tcontinue;\n\t\t\t\tcase 0x7F: \/\/ DEL\n\t\t\t\t\tif( 0 < len(line) ){\n\t\t\t\t\t\tline,_ = delTailChar(line)\n\t\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\tcase 'H'-0x40:\n\t\t\t\t\tif( 0 < len(line) ){\n\t\t\t\t\t\tline,_ = delTailChar(line)\n\t\t\t\t\t\tredraw(lno,line,right);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif( ch == '\\n' || ch == '\\r' ){\n\t\t\t\tfputc(ch,stderr);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tline += string(ch);\n\t\t\tredraw(lno,line,right);\n\t\t}\n\t\tEXIT:\n\t\tsystem(\"\/bin\/stty echo sane\");\n\t}\n\t\/\/fprintf(stderr,\"\\r\\nLINE:%s\\r\\n\",line);\n\nEXIT_GOT:\n\treturn line + right;\n}\n\nfunc getline_main(){\n\tline := xgetline(0,\"\",nil)\n\tfprintf(stderr,\"%s\\n\",line);\n\/*\n\tdp = strpbrk(line,\"\\r\\n\");\n\tif( dp != NULL ){\n\t\t*dp = 0;\n\t}\n\n\tif( 0 ){\n\t\tfprintf(stderr,\"\\n(%d)\\n\",int(strlen(line)));\n\t}\n\tif( lseek(3,0,0) == 0 ){\n\t\tif( romkanmode ){\n\t\t\tvar buf [8*1024]byte;\n\t\t\tconvs(line,buff);\n\t\t\tstrcpy(line,buff);\n\t\t}\n\t\twrite(3,line,strlen(line));\n\t\tftruncate(3,lseek(3,0,SEEK_CUR));\n\t\t\/\/fprintf(stderr,\"outsize=%d\\n\",(int)lseek(3,0,SEEK_END));\n\t\tlseek(3,0,SEEK_SET);\n\t\tclose(3);\n\t}else{\n\t\tfprintf(stderr,\"\\r\\ngotline: \");\n\t\ttrans(line);\n\t\t\/\/printf(\"%s\\n\",line);\n\t\tprintf(\"\\n\");\n\t}\n*\/\n}\n\/\/== end ========================================================= getline\n\n\/\/\n\/\/ $USERHOME\/.gsh\/\n\/\/\t\tgsh-rc.txt, or gsh-configure.txt\n\/\/              gsh-history.txt\n\/\/              gsh-aliases.txt \/\/ should be conditional?\n\/\/\nfunc (gshCtx *GshContext)gshSetupHomedir()(bool) {\n\thomedir,found := userHomeDir()\n\tif !found {\n\t\tfmt.Printf(\"--E-- You have no UserHomeDir\\n\")\n\t\treturn true\n\t}\n\tgshhome := homedir + \"\/\" + GSH_HOME\n\t_, err2 := os.Stat(gshhome)\n\tif err2 != nil {\n\t\terr3 := os.Mkdir(gshhome,0700)\n\t\tif err3 != nil {\n\t\t\tfmt.Printf(\"--E-- Could not Create %s (%s)\\n\",\n\t\t\t\tgshhome,err3)\n\t\t\treturn true\n\t\t}\n\t\tfmt.Printf(\"--I-- Created %s\\n\",gshhome)\n\t}\n\tgshCtx.GshHomeDir = gshhome\n\treturn false\n}\nfunc setupGshContext()(GshContext,bool){\n\tgshPA := syscall.ProcAttr {\n\t\t\"\", \/\/ the staring directory\n\t\tos.Environ(), \/\/ environ[]\n\t\t[]uintptr{os.Stdin.Fd(),os.Stdout.Fd(),os.Stderr.Fd()},\n\t\tnil, \/\/ OS specific\n\t}\n\tcwd, _ := os.Getwd()\n\tgshCtx := GshContext {\n\t\tcwd, \/\/ StartDir\n\t\t\"\", \/\/ GetLine\n\t\t[]GChdirHistory { {cwd,time.Now(),0} }, \/\/ ChdirHistory\n\t\tgshPA,\n\t\t[]GCommandHistory{}, \/\/something for invokation?\n\t\tGCommandHistory{}, \/\/ CmdCurrent\n\t\tfalse,\n\t\t[]int{},\n\t\tsyscall.Rusage{},\n\t\t\"\", \/\/ GshHomeDir\n\t\tTtyid(),\n\t\tfalse,\n\t\tfalse,\n\t\t[]PluginInfo{},\n\t\t[]string{},\n\t\t\" \",\n\t\t\"v\",\n\t\tValueStack{},\n\t\tGServer{\"\",\"\"}, \/\/ LastServer\n\t\t\"\", \/\/ RSERV\n\t\tcwd, \/\/ RWD\n\t\tCheckSum{},\n\t}\n\terr := gshCtx.gshSetupHomedir()\n\treturn gshCtx, err\n}\nfunc (gsh*GshContext)gshelllh(gline string)(bool){\n\tghist := gsh.CmdCurrent\n\tghist.WorkDir,_ = os.Getwd()\n\tghist.WorkDirX = len(gsh.ChdirHistory)-1\n\t\/\/fmt.Printf(\"--D--ChdirHistory(@%d)\\n\",len(gsh.ChdirHistory))\n\tghist.StartAt = time.Now()\n\trusagev1 := Getrusagev()\n\tgsh.CmdCurrent.FoundFile = []string{}\n\tfin := gsh.tgshelll(gline)\n\trusagev2 := Getrusagev()\n\tghist.Rusagev = RusageSubv(rusagev2,rusagev1)\n\tghist.EndAt = time.Now()\n\tghist.CmdLine = gline\n\tghist.FoundFile = gsh.CmdCurrent.FoundFile\n\n\t\/* record it but not show in list by default\n\tif len(gline) == 0 {\n\t\tcontinue\n\t}\n\tif gline == \"hi\" || gline == \"history\" { \/\/ don't record it\n\t\tcontinue\n\t}\n\t*\/\n\tgsh.CommandHistory = append(gsh.CommandHistory, ghist)\n\treturn fin\n}\n\/\/ <a name=\"main\">Main loop<\/a>\nfunc script(gshCtxGiven *GshContext) (_ GshContext) {\n\tgshCtxBuf,err0 := setupGshContext()\n\tif err0 {\n\t\treturn gshCtxBuf;\n\t}\n\tgshCtx := &gshCtxBuf\n\n\t\/\/fmt.Printf(\"--I-- GSH_HOME=%s\\n\",gshCtx.GshHomeDir)\n\t\/\/resmap()\n\n\t\/*\n\tif false {\n\t\tgsh_getlinev, with_exgetline :=\n\t\t\t which(\"PATH\",[]string{\"which\",\"gsh-getline\",\"-s\"})\n\t\tif with_exgetline {\n\t\t\tgsh_getlinev[0] = toFullpath(gsh_getlinev[0])\n\t\t\tgshCtx.GetLine = toFullpath(gsh_getlinev[0])\n\t\t}else{\n\t\tfmt.Printf(\"--W-- No gsh-getline found. Using internal getline.\\n\");\n\t\t}\n\t}\n\t*\/\n\n\tghist0 := gshCtx.CmdCurrent \/\/ something special, or gshrc script, or permanent history\n\tgshCtx.CommandHistory = append(gshCtx.CommandHistory,ghist0)\n\n\tprevline := \"\"\n\tskipping := false\n\tfor hix := len(gshCtx.CommandHistory); ; {\n\t\tgline := gshCtx.getline(hix,skipping,prevline)\n\t\tif skipping {\n\t\t\tif strings.Index(gline,\"fi\") == 0 {\n\t\t\t\tfmt.Printf(\"fi\\n\");\n\t\t\t\tskipping = false;\n\t\t\t}else{\n\t\t\t\t\/\/fmt.Printf(\"%s\\n\",gline);\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif strings.Index(gline,\"if\") == 0 {\n\t\t\t\/\/fmt.Printf(\"--D-- if start: %s\\n\",gline);\n\t\t\tskipping = true;\n\t\t\tcontinue\n\t\t}\n\t\tif false {\n\t\t\tos.Stdout.Write([]byte(\"gotline:\"))\n\t\t\tos.Stdout.Write([]byte(gline))\n\t\t\tos.Stdout.Write([]byte(\"\\n\"))\n\t\t}\n\t\tgline = strsubst(gshCtx,gline,true)\n\t\tif false {\n\t\t\tfmt.Printf(\"fmt.Printf %%v - %v\\n\",gline)\n\t\t\tfmt.Printf(\"fmt.Printf %%s - %s\\n\",gline)\n\t\t\tfmt.Printf(\"fmt.Printf %%x - %s\\n\",gline)\n\t\t\tfmt.Printf(\"fmt.Printf %%U - %s\\n\",gline)\n\t\t\tfmt.Printf(\"Stouut.Write -\")\n\t\t\tos.Stdout.Write([]byte(gline))\n\t\t\tfmt.Printf(\"\\n\")\n\t\t}\n\t\t\/*\n\t\t\/\/ should be cared in substitution ?\n\t\tif 0 < len(gline) && gline[0] == '!' {\n\t\t\txgline, set, err := searchHistory(gshCtx,gline)\n\t\t\tif err {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif set {\n\t\t\t\t\/\/ set the line in command line editor\n\t\t\t}\n\t\t\tgline = xgline\n\t\t}\n\t\t*\/\n\t\tfin := gshCtx.gshelllh(gline)\n\t\tif fin {\n\t\t\tbreak;\n\t\t}\n\t\tprevline = gline;\n\t\thix++;\n\t}\n\treturn *gshCtx\n}\nfunc main() {\n\tgshCtxBuf := GshContext{}\n\tgsh := &gshCtxBuf\n\targv := os.Args\n\tif 1 < len(argv) {\n\t\tif isin(\"version\",argv){\n\t\t\tgsh.showVersion(argv)\n\t\t\treturn\n\t\t}\n\t\tcomx := isinX(\"-c\",argv)\n\t\tif 0 < comx {\n\t\t\tgshCtxBuf,err := setupGshContext()\n\t\t\tgsh := &gshCtxBuf\n\t\t\tif !err {\n\t\t\t\tgsh.gshellv(argv[comx+1:])\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tif 1 < len(argv) && isin(\"-s\",argv) {\n\t}else{\n\t\tgsh.showVersion(append(argv,[]string{\"-l\",\"-a\"}...))\n\t} \n\tscript(nil)\n\t\/\/gshCtx := script(nil)\n\t\/\/gshelll(gshCtx,\"time\")\n}\n\/\/<\/div><\/details>\n\/\/<details id=\"todo\"><summary>Consideration<\/summary><div class=\"gsh-src\">\n\/\/ - inter gsh communication, possibly running in remote hosts -- to be remote shell\n\/\/ - merged histories of multiple parallel gsh sessions\n\/\/ - alias as a function or macro\n\/\/ - instant alias end environ export to the permanent > ~\/.gsh\/gsh-alias and gsh-environ\n\/\/ - retrieval PATH of files by its type\n\/\/ - gsh as an IME with completion using history and file names as dictionaies\n\/\/ - gsh a scheduler in precise time of within a millisecond\n\/\/ - all commands have its subucomand after \"---\" symbol\n\/\/ - filename expansion by \"-find\" command\n\/\/ - history of ext code and output of each commoand\n\/\/ - \"script\" output for each command by pty-tee or telnet-tee\n\/\/ - $BUILTIN command in PATH to show the priority\n\/\/ - \"?\" symbol in the command (not as in arguments) shows help request \n\/\/ - searching command with wild card like: which ssh-*\n\/\/ - longformat prompt after long idle time (should dismiss by BS)\n\/\/ - customizing by building plugin and dynamically linking it\n\/\/ - generating syntactic element like \"if\" by macro expansion (like CPP) >> alias\n\/\/ - \"!\" symbol should be used for negation, don't wast it just for job control\n\/\/ - don't put too long output to tty, record it into GSH_HOME\/session-id\/comand-id.log\n\/\/ - making canonical form of command at the start adding quatation or white spaces\n\/\/ - name(a,b,c) ... use \"(\" and \")\" to show both delimiter and realm\n\/\/ - name? or name! might be useful\n\/\/ - htar format - packing directory contents into a single html file using data scheme\n\/\/ - filepath substitution shold be done by each command, expecially in case of builtins\n\/\/ - @N substition for the history of working directory, and @spec for more generic ones\n\/\/ - @dir prefix to do the command at there, that means like (chdir @dir; command)\n\/\/ - GSH_PATH for plugins\n\/\/ - standard command output: list of data with name, size, resouce usage, modified time\n\/\/ - generic sort key option -nm name, -sz size, -ru rusage, -ts start-time, -tm mod-time\n\/\/   -wc word-count, grep match line count, ...\n\/\/ - standard command execution result: a list of string, -tm, -ts, -ru, -sz, ...\n\/\/ - -tailf-filename like tail -f filename, repeat close and open before read\n\/\/ - max. size and max. duration and timeout of (generated) data transfer\n\/\/ - auto. numbering, aliasing, IME completion of file name (especially rm of quieer name)\n\/\/ - IME \"?\" at the top of the command line means searching history\n\/\/ - IME %d\/0x10000\/ %x\/ffff\/\n\/\/ - IME ESC to go the edit mode like in vi, and use :command as :s\/x\/y\/g to edit history\n\/\/ - gsh in WebAssembly\n\/\/ - gsh as a HTTP server of online-manual\n\/\/---END--- (^-^)\/ITS more<\/div><\/details>\n\/*\n<details id=\"references\"><summary>References<\/summary><div class=\"gsh-src\">\n<p>\n<a href=\"https:\/\/golang.org\">The Go Programming Language<\/a>\n<iframe loading=\"lazy\" src=\"https:\/\/golang.org\" width=\"100%\" height=\"300\"><\/iframe>\n\n<a href=\"https:\/\/developer.mozilla.org\/ja\/docs\/Web\">MDN web docs<\/a>\n <a href=\"https:\/\/developer.mozilla.org\/ja\/docs\/Web\/HTML\/Element\">HTML<\/a>\n CSS:\n   <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/CSS_Selectors\">Selectors<\/a>\n   <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/background-repeat\">repeat<\/a>\n HTTP\n JavaScript:\n ...\n<\/p>\n<\/div><\/details>\n<div id=\"gsh-footer\" style=\"\">Fin.<\/div>\n<style id=\"gsh-style\">\n #gsh {border-width:1;margin:0;padding:0;}\n #gsh {font-family:monospace,Courier New;color:#ddf;font-size:8px;}\n #gsh header{height:100px;}\n #xgsh header{height:100px;background-image:url(GShell-Logo00.png);}\n #gsh-menu{font-size:14pt;color:#f88;}\n #gsh-footer{height:100px;background-size:80px;background-repeat:no-repeat;}\n #gsh note{color:#000;font-size:10pt;}\n #gsh h2{color:#24a;font-family:Georgia;font-size:18pt;}\n #gsh details{color:#888;background-color:#aaa;font-family:monospace;}\n #gsh summary{font-size:16pt;color:#24a;background-color:#eef;height:30px;}\n #gsh pre{font-size:11pt;color:#223;background-color:#faffff;}\n #gsh a{color:#24a;}\n #gsh a[name]{color:#24a;font-size:16pt;}\n #gsh .gsh-src{white-space:pre;font-family:monospace,Courier New;font-size:11pt;}\n #gsh .gsh-src{background-color:#faffff;color:#223;}\n #gsh-src-src{spellcheck:false}\n #src-frame-textarea{white-space:pre;font-family:monospace,Courier New;font-size:11pt;}\n #src-frame-textarea{background-color:#faffff;color:#223;}\n @media print {\n  #gsh pre{font-size:11pt !import;}\n }\n<\/style>\n<!--\n\/\/ Logo image should be drawn by JavaScript from a meta-font.\n\/\/ CSS seems not follow line-splitted URL\n-->\n<script id=\"gsh-run\">\nGshLogo=\"data:image\/png;base64,\\\niVBORw0KGgoAAAANSUhEUgAAAQEAAAB\/CAYAAADvs3f4AAAAAXNSR0IArs4c6QAAAHhlWElm\\\nTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAAB\\\nAAAATgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAQGgAwAE\\\nAAAAAQAAAH8AAAAAYx1BhgAAAAlwSFlzAAALEwAACxMBAJqcGAAAF3RJREFUeAHtnQuUFNWZ\\\nx++t7ukZ3iCggO\/jY6Osb8WgMzAvn7uG4+bISTR7YnQXdQPCkGj2aNwlD2MSlRkeUaPnoCdu\\\n4iuJx7jriYZ50DOGmF2VqIBEiSggCoiMMA+mu+vu\/\/ZMD9U1dau6a2aUbv91GKrq3vvdx6\/q\\\nfnXvdx8tBA8SIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAES\\\nIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAES\\\nIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAES\\\nIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIIFDl4A8dLP2\\\n2eXs9H9+ftSkSdHxsic2qqdE7YusS+1qaalKfnY5YsokMHwEPtdK4MQFz5UeExlbLYSaYUl5\\\nnpDiLKXEZClFiRM53JSUaq9ScqcU6i+2kK3StuONy5reEGKJ7Qw7mOvKec2ToqOiZwoljhFS\\\njbOVHCstMRb3USXEJ8hFu7DsdmFb2+xU4vWWFVXbBpMeZUlAE\/hcKoGab66eKGOlNykh56PC\\\nHxH2VVBKoRKqh3qUeKi1YdaOfONJ56OkdI6w5BwomnOQlyPzi0N9DLmXpFK\/60p2P\/Piyovf\\\nN8mfM+\/nJWNGnjw9KqOToLVGSFt2p2Ril1gn3ij0Vk7YsoWVMzEuVPfPlRKYdfOak2LRSB0q\\\nzrWocCOG6qEhvgRaCj\/dktj3g7dXXH4gKN6aRS0zpYzerqS6RAoZDQqfk79SKTRXHu\/e+9FN\\\nL66as88pU\/PN1pNlTLQJKSc73dPXSr20ur7iiwPcC8QhbNnCyhUIlryyOTQvYF5JfvqBL7jx\\\n+cNHjBj5gJRyDlJHy39o84D40H2Qtx8THaPeFuIOU+w1C+KnyhK5FGEv0WGgAExB83eXMoLY\\\nrikbd9gHEP52VgQl4h89FUA6kJyYFbbQbnzLJg4zFiesnDHCwvUoeiVQOb\/5C9FY9DlUueOH\\\n+zGhUh9nSqOqrm0uWgurkI9RpjBD4Y6uQcQdD5TUOW63zD3MHesy14V49isbdKyxbGHlCpFR\\\nUJ6toACF7F9VF58NBfDHT0MBaE74Ent+eWrrWr+Lz\/QTw60AdB7QJUjps\/OA7cOoBNBCeMUZ\\\nttCu\/coG28fLpvKElTPFV8juRasEahbHvxaR1guoeBPyfUDo4+OfeBdyb8L4tz9XeSXFAMOc\\\nbgGgov0g1zgGGw4jF392xnHhdc+Mwf3JTjfntZ2yC1YJBJXNUt5KIKyck1sxXRdld6BmcevN\\\naJovy\/VBacMevqEP46\/ZlnJjt9jx17VL53Zl5Mtvap1QGlNHw5pQDqXyNTQlZ2b8nGcMG2ZV\\\nqOoFjSdYvV0AZzDfayidv6FJ35CS4jXZk9hir7e27zm6p3T8hLJpkYicJpV1HtK\/DJFU4Jw1\\\nlImhxM5IR9fzzgRKx4w\/C+HQSPE+krbIyrN3qEPTNahsHaLDs2xh5Q5NCoPPVdEpgcqbm\/8e\\\n7\/zdOaHptag\/mlKJ77U0VG0xybTdX\/Ex\/PTfa\/i7r7Ku+cSoiCxUwrohUxF16wEV9H+ccVgl\\\npd\/CfU42AK2IUPlvTK1L\/sJjyE5PVHqr728NzvfUzvvDODGy9GoopuuhmNLNfcTx48YHL2qH\\\nf\/8hpXVu\/43rQg9xtq6YtcvlXDC3fmWDQn9nbf2le7wKE1bOK65icBu0Eqhd3IaW82dwKPUw\\\nhrauc6ZcWdkcjUZK8EUXMae71zUqwCu2nbi6eVn1Ji9\/P7eW+ioMAogF+NI3iJLSf8dn9ipA\\\nWNW4rPy9jJxuPeDL\/HXzNzgTsveslD2vsWHWI9mu5rvVvZX9foS4v\/LfmqdEIpHDGlfM2uCW\\\ngJIy2wOENPaZ3fEcivd+ZYNCNJYtrNyhyGAo8jRoJTAUmRiqOCJnRW5FpTN++frTwdh4SiUv\\\nbVlWvbffLcRF04qazRD7176\/rBjKylD5pBiZ5Wi4wQu7tikPBeCOpuW+Kj0sqP8GHNoAZuwL\\\niOzuywDhQ9zBr2xoDRqVQFi5QxxH6OwVjRKAAW46pvT+RxAJVLjW7vY9\/+CeUBMkl68\/rPQn\\\nmCufKzaldFN\/yI8gA5iwC3dkIKhsyvZuCYSVG\/KHcwhFWDRKAMMcD8EKX+rHFl2A9bt2d172\\\n2qNzOvzCDYmfEtNy7QogXDXWIKAIQ7cOQZchyADWnerqN5xVXttcJsdGp2OtwqmWJU7A+Eh7\\\nyhYbUgm1IX7f7K1DwaRyUfN42FIuxNDdVEtamL6sYC9R26VtbZaW2px8Nfmehz3EM+mgsolk\\\nd3\/ZnBGElXPGUWzXg1YCq5eW5\/zBGy54aWOgwWKfnWbqptcevWT4FUBvov32gew8DLzDTMaj\\\naupq7t\/bMXX+yw\/egJGKoTksy2d+gFBb9VoDvX5BlZTOR+Wfjyb0pP6U0XGOYNqR\/quta3vB\\\nFgeua6qv2d7vn8dFdV3rldBw34GSPg9i0DG9h5XWknh9kAaMmyJ6dklPzZmtD3cnu77vtw5C\\\nh\/YrG1p7Wxp\/VvuRDuc+wsq54ymm+8zzKOgyRSPRa4IKoGz1i8b6ytagcEPmb9v\/m09cUATz\\\nJow6tVnPcMxHzj+sNNpHsCJyja6csrRsMyrGkiwF4I5UiouliL1RW7fmNLeX3z2+\/GfW1LU2\\\nY572b6EAzkfYoPctJi15Q1nJyLdrFrUZp1\/3pmkuG\/yN9gAoGyMTf7neVIvx\/6CHUghlluh\/\\\nf9Uvo+gG7O3q7rzFL8xQ+zW+\/8F6PW6fV7xSXhiNlayvWdz2X1ULm\/4uL1mPwNoA5uGcdoL9\\\nZFa6cgoxzhTG6Q4lNR5Doj9xuvlcy+rFbcujVsnLkKv0CefphUbICLRMvl+9KP4vngHg6Fc2\\\nNCqMSiCsnCkfxeD+mTflBwuxdmFbOZqT\/l94225Y3TCrzpQWhthG2zHraJO\/yb0kkdhpanZq\\\nGXwFf66\/8Cb5AHcbzdpnhUjeG6YFow1gZeMmtqNCDekzTiXVuc3LK4yVTJepuq5tqSWFkXdA\\\nufu9MfWiG3sqnNtcX76+3xEXQWWzVeqSpvrZmC2afYSVy46l+O4KvyVgicCugG2rp0yPTveJ\\\no2Ulm2JWZEO+f6K0dFtNXfw2U9x7O\/bqZct5z0Poi0+vdpyDJcdxrD34U9XCeHrloSktt3ug\\\nAcwtkOO9FZFn+gWtWdS6ODcFoDrAxneOCfRXWUSoK93pBZXN7vAe+gwr506\/2O4LXgngLbrC\\\n76HgRdvetHz2WlMYVVqqm5zTTP5+7volRR\/zJlOYlx+8ohOzEb+CV\/0TU5ic3NGfjkSs30MZ\\\ntFUtil+Yi4yfAcwkjzqpZyb6HlgJebwpgLYxoO9\/j8k\/\/WW3xS32gQPHrV5aMTp1IDFN2Op6\\\nfz5ywF4HfmXD+\/Buy4NVu73yEFbOK65icot+ZjP+8qf4JkYiTnGKTb\/qST0zMKACq18jjPGL\\\nA4PCxYNpMKOtjREv84HpyOsws\/BsqyT2RGZ6rzl0gA9sBhEp46hsP2ratmOJeGrugBWDB2Pw\\\nNYD1B4OSTMBmcmdS2E\/GG2ZvrF7Uejsqyw\/7A7guEH6Kyyl9q3fpQQvgXtx4dz+Ueg+Lmy5v\\\nbjjYtO+b5LSqpq5Nz6nwbFFhUdaYgemZy4ap1z5dlbByA3NQTC4F3RKYfOTkaUF9Xry0LwU8\\\nsDMC\/H29oV0GTNV1C+iZhTu27rgAebkb4+8H3P553qOOyu\/WHj21ZWbd7z2XLuv4fA1gmQSV\\\n2GML+6KmhorvaQWgne11yZ\/glLX+IBNcn2FQ7F9Y5XQfN\/qUa+Hr3UrAGg1MTLrG3bfPyEtp\\\nm6d5oyCZcJmzX9nQ2jAqgbBymXSL9VzQSgBfxUBjHpbXbzM+vKueRBRiotE\/Bw8ogf\/LIZhY\\\n\/9Tcnsb68lt7DtgnQRE8lEvT2z9eWT5SjF7lFSZoVlyfTLvqUTOb62etccbRO1lHeS68SYeT\\\n2OzUdegWmRTW7S7ng7dKrVi9rLztoMPBK73nA4YrdZfM+5DZsymDymaHnClokvPOVHG5FrQS\\\nwCY6RwU9Dkx5MU9wQXMaX+ePguLw8\/dvfg6U1LPvsPBpXspOniQwagElsm9gqNxctOEQlvj5\\\n7tBBBjAdHkMPdY0\/q\/irW1bf44t5cNKQKwAq7DsuJzHl6Clz8bk+1u2u78FXYWfklQ4\/qY2x\\\ntYvjX8boyWN6zwc9\/Ojwz7pUtv1Lp0NQ2UxLo8PKOdMu1uvooTDjLyxcrNWHEhjQWsyKrkPs\\\n2JHl4LpJicQXoyp6nMs5fYsKeile0G95+WXcEj3m5mcmjNe5b+lyHZYELxGjRmDnY\/HtMK0S\\\naPE7Md34PueUYz8DWDovSjzXVF\/xsFe+Lpz\/wjQQ9eiH94ZWqVS62+CUhV3lMtNjSHfXorHf\\\nwKgZg9FwIrTCRJwjWh5+\/ocSLzQ1zG52BvItG+wOpqXRYeWcaRfrdbSgC5bD\/PySxBHakPWO\\\nqZx9y4L10uABB4xk5we8qDsHO6++b0nwjzFXYaUViy6Ece0O1I7SAZkxOUgxtmZB9RcaVyxx\\\n2CbMBjAdTcruWWyKriwy4myTH9zt3R93\/8Xlj0ESWetyy7qFIj1odwkAmhFEA2KD6DlwNe6h\\\nH52HuWwIaLQHQOUYZwr6yznTLs7rgu4OYBJq4JBWJCayRhTyeYx4X8\/xCw+rus9L5yc50A+W\\\n8v0w0N2ZxAw7VADPZcEDpXpdsLXoDKefrwEM+yj47aEAa7yxzMjXm+61FzUL46ch7cOd6Q\/m\\\nWncf9BTvXbs6Z3hNxPIvm1kJhJUbTFkKRbaglQCWiwbuiiPtyKlhHwZaq8YKoeMcji9Iy9Ly\\\nPwk79U\/55Bk75fSXMchwhj79Y35xY7qu8YspvTbqSG+55hdjjn6YS6ErfyqVOL2xoeLrbmWj\\\nYwkqG5S2p1IOK5djzgs+2LB1B4Z6\/gG+uosa6yuWOYljzcCuoG4llqxVQOYep1wu1xUL4pPR\\\nzD3GL6wlVE4jA35xePk1NlSuBb\/34RcwB6JXGgz6rflBBjBbJH7tlWbGDRVdb4bieXgpPbhN\\\nNQT3iqMHz7ETHvuRxnv45r8FpfQWRnDiqVfV2qBlxEFl6+rqDLV82CTnVYBidBs2JfBpwMJP\\\naW3rXYbqm9qXMLnmChjCnvUN5fKMRc2LbzJBk8mU55cn4x\/2rLdJQzNjtKkyuuO1pdqccfMz\\\ngKGp\/aHfXooVi+JTofimZuJyn8F7QHmhAMxdAaUeTX6c7F07sUUkgyq5Oz33vV\/Z0C7b+scH\\\nLtnpltH3YeW84ipGt4JWAnu7Pn5xwqjxB4IMabBc3Q8rfLzPCJfTc0SF0b8NaDzSFWqYfhBU\\\nnm1djITHGhN3eSRt+42Mk5KWcTsxFMe35RJTvorP3rmn49VMOgfP8oiD19lX6IdvbXmkqjvb\\\nNfydX9m8WimZlMLKZeSL\/VzQSkDPzcdYcyte7lq\/B4XKfKQaNeK3mL47r29fQL\/gaT+\/vrEO\\\ngDTTX0U9UWbKUVMfh9MYuLZjVPzxxu0fPO0\/pTedhOd\/1XXxGZawfuXp6eGIlz+eme2X9lbo\\\n0xuUl19F0bLaKGgQhafa5NVPhxjK7X0gLuOMRm+JAFefsnnaKzLRhZXLyBf5ediUwKc1\/wD7\\\nfD+JL72vEtDPEIqgWkZj6zFP\/d5duzt+ZHihxfkLnhs7umT0l1AjKkyVScenpJ1WAlAACzAE\\\ndqV2Sx\/S+nLN0dPelXVtD\/SkUr+JL5\/9VsbL75z+bYNS8Q2EuQN\/Oa3x1\/FJZS\/VZ30EGcBg\\\nePdtCYCR0RCKr3q6vL0pOf7XfXvDAaVzcGjQECZX56CyYcmxZ\/7CyuWar2IIN2xK4NOC075\/\\\n4yMTRk3XuwyfGJgmxt\/xdbpt8uSRi7Fl1luoFJtQm3Ul7cKXfyqMVsfDvwpVq9RPAeh07FRv\\\nhUL4693pwu1YyN+FX0C+Cy0VrIWXzylh\/w3n7fiibreUtTsVURMitjpKWRYmPKkZmHDzFciM\\\ndMflf6+eWl0\/65lMmCDD2YFEl2dFycgj38aRAbQSPGX1sCGUcCaKrDOUyszauvgcZx6zAvTf\\\nLLGqFlXPjFjyIthCkphR+cN+r76LoLJ1d3d45i+snDv9Yr4veCWg9+SrXtx6G\/arezLXB4WX\\\ntgzv7Wk4n+Z8f\/FFzzUKIa3ky5ULmo9CE8N3HgLinI5IsRNy32hsXxoRnTBmBvWmiP9zT7o3\\\nj0q8vnN35zecGfY1gCm1w2\/fviCjoJXytieolL0xvRGhMyNZ1\/IJtL6Ww3j5y8j+7i1dyU57\\\nxLjDJmM+xOFQgtrucgEUTDVIpFcnovWAf2KAEvArG5T3tjBGQT+5rCIU+U1BzxPIPJumpRVP\\\n4YEuz9wP9xlfvw\/0ppuyxDp9uNPyih9l\/XNXovNSd5dGG8C8wms31CzfrkCQUTCZSHj+wm8q\\\nJV7XE3xM6WqjLSr6LVB668ToEXtHjJ\/4Cdw24+uzFvsJrsT11RkFoOOALtznFZdf2SDl2QrQ\\\n8YSV88pDsboVhRLQD6exvrEOj9y4g9DQPkC5Zmjjyz021LdV7yb3zfL8qmsDmOFARTVWFC3i\\\nN1NQGwX1jEavqOMrZ78D2ZVefmHcdPfCU86nbFBB5rKFlfPMRHE6Fo0S0AtoVm\/d8VV8km7D\\\nC58YrseFuLvspLpbx79z64erdZNyuNLKileJdalUak7j0orr315x+YA9CbQBDF\/ck7JkHDdB\\\nE5sg69OKMH9pdRJd6v3vgEvYbdQcucSlVM9nO\/QaPP3KZlve8zWCmJjk3OkX+30RKQE8KiwN\\\nblxafhe29JqBL8of8GKam6n5P9mdGP5bmUikpmc22tR7BHSKjjP0kmCktCf\/KAMlsOJXtejK\\\nv7q+\/OzmZbN\/Z5IoHT3+NPgZn2eyx7uiZOJDM9xoyTcZBTOya+vndqW3URPijYxbmDOe1\/au\\\nzq4BrYqgslmphGdLIKxcmLwXskzBGwa94OstveB+sf714IiK3oiO5mXod+r9\/I2VxB0P9Ec3\\\nxp7XQYu8JGTqmcatO+NeY\/99v3xbh+21bh03cnotljdfCZnzkeapSDN\/vjDg4XP4Cnb8+W9p\\\n9zzduKz2Q3fevO5lytqtomo30pzk9Ec5sHOY+FXfVl5Or6xr5HkDFMGAadKQ3yAO9DydFdjj\\\nppf5kjNq6qrnYi3DfyKI5h14oOKj1aZehBJ9NtWTfBAGvv1uIawS2xVTahfsB5OdfrpseEaP\\\nmRiFlXOm8Xm4xnP\/fBy6aVg2fty5SkWno2mMPfSF3sgCf3o4UGGSj\/wI548wVLfbVvab7Z0b\\\nXx\/MrwGlf9ZrXPQMbMx5CiAfjiHIyXjhsR7BKkMfG8mLT+D3CdJF2qod1vNN3V3d60xW7hyf\\\nkoSVf0pEpkZFeqJWQtld70c6dnp1H7zi0z933hOLHWYJu1REhZ7ptxeVe69XWH+3Jdasm6tO\\\niEWsY1G5j8Eaj2NR0adga7IeVOR2LBSCcVC8Z0u5Ue1JbspxVqHEcusjRKkYLW0VSSUinTmW\\\nLaycfxHpSwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk\\\nQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk\\\nQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk\\\nQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk\\\nQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk\\\nQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAJ5Evh\/ikTb\\\nm38w0ncAAAAASUVORK5CYII=\";\n\nITSmoreQR=\"data:image\/png;base64,\\\niVBORw0KGgoAAAANSUhEUgAAAG8AAABvAQMAAADYCwwjAAAABlBMVEX\/\/\/9BaeFHqDaJAAAB\\\nHklEQVQ4jdXTsa2EMAwGYCMX7sICkVgjXVaCBe7CArASXdaIlAWgS4HwM5zEVS+mvSgS+ZBQ\\\n8gcb4BdHyzwv8szMSaUBHNm+KAd4QC8LDpDn8ogT4UpPGci2jI8IGFx3eLwPWaHknVyWecev\\\nUEbDXaB0X2aNjueYDOzNklQassPCkjc4nW3E1SfwqYk6jU\/vAkPhg0AlSFhve8Jt0dkwDMwr\\\nyMGSSuPyWHAr19k0tkV2sb3sdW2rUCqW88g4Rp1A9s1JPv9cTp1NRD4XFkin8XaQCIwT6Lzq\\\nZO8dHw\/4+U2GzqlS8gbqVmkfr1N6YXK8OqlD0OmlGTMvzPERA8AL9vvbOifpSoL33fsVytrL\\\nS9wiqDzznhUI38v5n783\/gBuUs2eLg1c8gAAAABJRU5ErkJggg==\";\n\ndocument.getElementById('banner').style.backgroundImage=\"url(\"+GshLogo+\")\";\n\/\/document.getElementById('gsh-footer').style.backgroundImage=\"url(\"+\"QR-ITS-more.jp.png\"+\")\";\ndocument.getElementById('gsh-footer').style.backgroundImage=\"url(\"+ITSmoreQR+\")\";\n\/\/https:\/\/www.w3schools.com\/JSREF\/prop_style_backgroundposition.asp\nvar bannerStop = false\nfunction shiftBG(){\n bannerStop = !bannerStop\n document.getElementById('banner').style.backgroundPosition = \"0 0\";\n}\n\nfunction html_fold(){\n document.getElementById('index').open=false\n document.getElementById('gsh-gocode').open=false\n document.getElementById('todo').open=false\n document.getElementById('reference').open=false\n}\nfunction html_open(){\n document.getElementById('index').open=true\n document.getElementById('gsh-gocode').open=true\n document.getElementById('todo').open=true\n document.getElementById('reference').open=true\n}\nfunction html_stop(){\n bannerStop = !bannerStop\n}\n\n\/\/https:\/\/www.w3schools.com\/jsref\/met_win_setinterval.asp\nfunction shiftBanner(){\n var now = new Date().getTime();\n \/\/\"console.log(\"now=\"+(now%10))\n if( !bannerStop ){\n  document.getElementById('banner').style.backgroundPosition = ((now\/10)%100000)+\" 0\";\n }\n}\nsetInterval(shiftBanner,10);\n\n\/\/ from embedded html to standalone page\nfunction html_close(){\n\twindow.close()\n}\n\n\/\/ from embedded html to standalone page\nfunction html_new(){\n\tnewwin = window.open(\"\",\"\",\"\");\n\tsrc = document.getElementById(\"gsh\");\n\tnewwin.document.write(\"\/*<\"+\"html>\\n\");\n\tnewwin.document.write(\"<\"+\"span id=\\\"gsh\\\">\");\n\tnewwin.document.write(src.innerHTML);\n\tnewwin.document.write(\"<\"+\"\/span><\"+\"\/html>\\n\"); \/\/ gsh span\n\tnewwin.document.close();\n\tnewwin.focus();\n}\n\n\/\/ source code viewr\nfunction frame_close(){\n\tsrcframe = document.getElementById(\"src-frame\");\n\tsrcframe.innterHTML = \"\";\n\t\/\/srcframe.style.cols = 1;\n\tsrcframe.style.rows = 1;\n\tsrcframe.style.height = 0;\n\tsrcframe.style.display = false;\n\tsrc = document.getElementById(\"src-frame-textarea\");\n\tsrc.innerHML = \"\"\n\t\/\/src.cols = 0\n\tsrc.rows = 0\n\tsrc.display = false\n\t\/\/alert(\"--closed--\")\n}\n\/\/<!-- | <span onclick=\"html_view();\">Source<\/span> -->\n\/\/<!-- | <span onclick=\"frame_close();\">SourceClose<\/span> -->\n\/\/<!--| <span>Download<\/span> -->\nfunction frame_open(){\n\toldsrc = document.getElementById(\"GENSRC\");\n\tif( oldsrc != null ){\n\t\t\/\/alert(\"--I--(erasing old text)\")\n\t\toldsrc.innterHTML = \"\";\n\t\treturn\n\t}else{\n\t\t\/\/alert(\"--I--(no old text)\")\n\t}\n\tbanner = document.getElementById('banner').style.backgroundImage;\n\tfooter = document.getElementById('gsh-footer').style.backgroundImage;\n\tdocument.getElementById('banner').style.backgroundImage = \"\";\n\tdocument.getElementById('banner').style.backgroundPosition = \"\";\n\tdocument.getElementById('gsh-footer').style.backgroundImage = \"\";\n\n\tsrc = document.getElementById(\"gsh\");\n\tsrcframe = document.getElementById(\"src-frame\");\n\tsrcframe.innerHTML = \"\"\n\t + \"<\"+\"cite id=\\\"GENSRC\\\">\\n\"\n\t + \"<\"+\"style>\\n\"\n\t + \"#GENSRC textarea{tab-size:4;}\\n\"\n\t + \"#GENSRC textarea{-o-tab-size:4;}\\n\"\n\t + \"#GENSRC textarea{-moz-tab-size:4;}\\n\"\n\t + \"#GENSRC textarea{spellcheck:false;}\\n\"\n\t + \"<\/\"+\"style>\\n\"\n\t + \"<h2>\\n\"\n\t \/\/+ \"<\"+\"span onclick=\\\"frame_close();\\\">Close<\/\"+\"span>\\n\"\n\t \/\/+ \" | <\"+\"span onclick=\\\"html_stop();\\\">Run<\/\"+\"span>\\n\"\n\t + \"<\/h2>\\n\"\n\t + \"<\"+\"textarea id=\\\"src-frame-textarea\\\" cols=100 rows=40>\"\n\t + \"\/*<\"+\"html>\\n\"\n\t + \"<\"+\"span id=\\\"gsh\\\">\"\n\t + src.innerHTML\n\t + \"<\"+\"\/span><\"+\"\/html>\\n\"\n\t + \"<\/\"+\"textarea>\\n\"\n\t + \"<\/\"+\"cite><!-- GENSRC -->\\n\";\n\n\t\/\/srcframe.style.cols = 80;\n\t\/\/srcframe.style.rows = 80;\n\n\tdocument.getElementById('banner').style.backgroundImage = banner;\n\tdocument.getElementById('gsh-footer').style.backgroundImage = footer\n}\nfunction html_view(){\n\thtml_stop();\n\n\tbanner = document.getElementById('banner').style.backgroundImage;\n\tfooter = document.getElementById('gsh-footer').style.backgroundImage;\n\tdocument.getElementById('banner').style.backgroundImage = \"\";\n\tdocument.getElementById('banner').style.backgroundPosition = \"\";\n\tdocument.getElementById('gsh-footer').style.backgroundImage = \"\";\n\n\t\/\/srcwin = window.open(\"\",\"CodeView2\",\"\");\n\tsrcwin = window.open(\"\",\"\",\"\");\n\tsrcwin.document.write(\"<span id=\\\"gsh\\\">\\n\");\n\n\tsrc = document.getElementById(\"gsh\");\n\tsrcwin.document.write(\"<style>\\n\");\n\tsrcwin.document.write(\"textarea{tab-size:4;}\\n\");\n\tsrcwin.document.write(\"textarea{-o-tab-size:4;}\\n\");\n\tsrcwin.document.write(\"textarea{-moz-tab-size:4;}\\n\");\n\tsrcwin.document.write(\"<\/style>\\n\");\n\tsrcwin.document.write(\"<h2>\\n\");\n\tsrcwin.document.write(\"<\"+\"span onclick=\\\"window.close();\\\">Close<\/span> | \\n\");\n\t\/\/srcwin.document.write(\"<\"+\"span onclick=\\\"html_stop();\\\">Run<\/span>\\n\");\n\tsrcwin.document.write(\"<\/h2>\\n\");\n\tsrcwin.document.write(\"<textarea id=\\\"gsh-src-src\\\" cols=100 rows=60>\");\n\tsrcwin.document.write(\"\/*<\"+\"html>\\n\");\n\tsrcwin.document.write(\"<\"+\"span id=\\\"gsh\\\">\");\n\tsrcwin.document.write(src.innerHTML);\n\tsrcwin.document.write(\"<\"+\"\/span><\"+\"\/html>\\n\");\n\tsrcwin.document.write(\"<\/\"+\"textarea>\\n\");\n\n\tdocument.getElementById('banner').style.backgroundImage = banner;\n\tdocument.getElementById('gsh-footer').style.backgroundImage = footer\n\n\tsty = document.getElementById(\"gsh-style\");\n\tsrcwin.document.write(\"<\"+\"style>\\n\");\n\tsrcwin.document.write(sty.innerHTML);\n\tsrcwin.document.write(\"<\"+\"\/style>\\n\");\n\n\trun = document.getElementById(\"gsh-run\");\n\tsrcwin.document.write(\"<\"+\"script>\\n\");\n\tsrcwin.document.write(run.innerHTML);\n\tsrcwin.document.write(\"<\"+\"\/script>\\n\");\n\n\tsrcwin.document.write(\"<\"+\"\/span><\"+\"\/html>\\n\"); \/\/ gsh span\n\tsrcwin.document.close();\n\tsrcwin.focus();\n}\n<\/script>\n-->\n*\/ \/\/<\/span><\/html>\n","protected":false},"excerpt":{"rendered":"<p>\u958b\u767a\uff1a\u6a5f\u80fdGShell\u3067\u30ea\u30e2\u30fc\u30c8\u30b3\u30de\u30f3\u30c9\u3092\u5b9f\u88c5\u3057\u3066\u308b\u6642\u306b\u601d\u3063\u305f\u306e\u3067\u3059\u304c\u3001\u3084\u306f\u308a\u4e00\u672c\u306e\u30b9\u30c8\u30ea\u30fc\u30e0\u4e0a\u3067\u30bd\u30d5\u30c8\u306bEOF\u3068\u3044\u3046\u304bEOR\u3092\u9001\u308b\u306e\u306f\u96e3\u3057\u3044\u304b\u306a\u3068\u3002 \u793e\u9577\uff1a\u306a\u306e\u3067\u5236\u5fa1\u7528\u3068\u306f\u5225\u306b\u6bce\u56deTCP\u3092\u5f35\u3063\u3066\u4f7f\u3044\u6368\u3066\u308b\u3068\u3044\u3046\u8a08\u753b\u3067\u3059 &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/its-more.jp\/ja_jp\/?p=15096\" class=\"more-link\"><span class=\"screen-reader-text\">\"GShell 0.2.1 \u2212 \u30c4\u30a4\u30b9\u30c8\u30b9\u30c8\u30ea\u30fc\u30e0\" \u306e<\/span>\u7d9a\u304d\u3092\u8aad\u3080<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=\/wp\/v2\/posts\/15096"}],"collection":[{"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=15096"}],"version-history":[{"count":32,"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=\/wp\/v2\/posts\/15096\/revisions"}],"predecessor-version":[{"id":15586,"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=\/wp\/v2\/posts\/15096\/revisions\/15586"}],"wp:attachment":[{"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=15096"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=15096"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/its-more.jp\/ja_jp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=15096"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}