diff options
author | Caleb Maclennan <caleb@alerque.com> | 2023-11-10 09:12:04 +0300 |
---|---|---|
committer | Caleb Maclennan <caleb@alerque.com> | 2023-11-10 09:12:04 +0300 |
commit | 5c4fc93d5f4137bf4c22ddf1a048c907a4a26727 (patch) | |
tree | a9a68e1f6a9c3bfe2b64fa1c3a4098865b7d3b5d /etc | |
parent | ccef3bc4e2aa6ee5b997a80aabb58f4ff0b0e98f (diff) | |
parent | 43a97b7f0053313b43906371dbdc226271e6c8ab (diff) | |
download | luasocket-hjelmeland-patch-1.tar.gz luasocket-hjelmeland-patch-1.tar.bz2 luasocket-hjelmeland-patch-1.zip |
Merge branch 'master' into hjelmeland-patch-1hjelmeland-patch-1
Diffstat (limited to 'etc')
-rw-r--r-- | etc/README | 89 | ||||
-rw-r--r-- | etc/b64.lua | 19 | ||||
-rw-r--r-- | etc/check-links.lua | 111 | ||||
-rw-r--r-- | etc/check-memory.lua | 17 | ||||
-rw-r--r-- | etc/cookie.lua | 88 | ||||
-rw-r--r-- | etc/dict.lua | 151 | ||||
-rw-r--r-- | etc/dispatch.lua | 307 | ||||
-rw-r--r-- | etc/eol.lua | 13 | ||||
-rw-r--r-- | etc/forward.lua | 65 | ||||
-rw-r--r-- | etc/get.lua | 141 | ||||
-rw-r--r-- | etc/links | 17 | ||||
-rw-r--r-- | etc/lp.lua | 323 | ||||
-rw-r--r-- | etc/qp.lua | 23 | ||||
-rw-r--r-- | etc/tftp.lua | 154 |
14 files changed, 0 insertions, 1518 deletions
diff --git a/etc/README b/etc/README deleted file mode 100644 index cfd3e37..0000000 --- a/etc/README +++ /dev/null | |||
@@ -1,89 +0,0 @@ | |||
1 | This directory contains code that is more useful than the | ||
2 | samples. This code *is* supported. | ||
3 | |||
4 | tftp.lua -- Trivial FTP client | ||
5 | |||
6 | This module implements file retrieval by the TFTP protocol. | ||
7 | Its main use was to test the UDP code, but since someone | ||
8 | found it usefull, I turned it into a module that is almost | ||
9 | official (no uploads, yet). | ||
10 | |||
11 | dict.lua -- Dict client | ||
12 | |||
13 | The dict.lua module started with a cool simple client | ||
14 | for the DICT protocol, written by Luiz Henrique Figueiredo. | ||
15 | This new version has been converted into a library, similar | ||
16 | to the HTTP and FTP libraries, that can be used from within | ||
17 | any luasocket application. Take a look on the source code | ||
18 | and you will be able to figure out how to use it. | ||
19 | |||
20 | lp.lua -- LPD client library | ||
21 | |||
22 | The lp.lua module implements the client part of the Line | ||
23 | Printer Daemon protocol, used to print files on Unix | ||
24 | machines. It is courtesy of David Burgess! See the source | ||
25 | code and the lpr.lua in the examples directory. | ||
26 | |||
27 | b64.lua | ||
28 | qp.lua | ||
29 | eol.lua | ||
30 | |||
31 | These are tiny programs that perform Base64, | ||
32 | Quoted-Printable and end-of-line marker conversions. | ||
33 | |||
34 | get.lua -- file retriever | ||
35 | |||
36 | This little program is a client that uses the FTP and | ||
37 | HTTP code to implement a command line file graber. Just | ||
38 | run | ||
39 | |||
40 | lua get.lua <remote-file> [<local-file>] | ||
41 | |||
42 | to download a remote file (either ftp:// or http://) to | ||
43 | the specified local file. The program also prints the | ||
44 | download throughput, elapsed time, bytes already downloaded | ||
45 | etc during download. | ||
46 | |||
47 | check-memory.lua -- checks memory consumption | ||
48 | |||
49 | This is just to see how much memory each module uses. | ||
50 | |||
51 | dispatch.lua -- coroutine based dispatcher | ||
52 | |||
53 | This is a first try at a coroutine based non-blocking | ||
54 | dispatcher for LuaSocket. Take a look at 'check-links.lua' | ||
55 | and at 'forward.lua' to see how to use it. | ||
56 | |||
57 | check-links.lua -- HTML link checker program | ||
58 | |||
59 | This little program scans a HTML file and checks for broken | ||
60 | links. It is similar to check-links.pl by Jamie Zawinski, | ||
61 | but uses all facilities of the LuaSocket library and the Lua | ||
62 | language. It has not been thoroughly tested, but it should | ||
63 | work. Just run | ||
64 | |||
65 | lua check-links.lua [-n] {<url>} > output | ||
66 | |||
67 | and open the result to see a list of broken links. Make sure | ||
68 | you check the '-n' switch. It runs in non-blocking mode, | ||
69 | using coroutines, and is MUCH faster! | ||
70 | |||
71 | forward.lua -- coroutine based forward server | ||
72 | |||
73 | This is a forward server that can accept several connections | ||
74 | and transfers simultaneously using non-blocking I/O and the | ||
75 | coroutine-based dispatcher. You can run, for example | ||
76 | |||
77 | lua forward.lua 8080:proxy.com:3128 | ||
78 | |||
79 | to redirect all local conections to port 8080 to the host | ||
80 | 'proxy.com' at port 3128. | ||
81 | |||
82 | unix.c and unix.h | ||
83 | |||
84 | This is an implementation of Unix local domain sockets and | ||
85 | demonstrates how to extend LuaSocket with a new type of | ||
86 | transport. It has been tested on Linux and on Mac OS X. | ||
87 | |||
88 | Good luck, | ||
89 | Diego. | ||
diff --git a/etc/b64.lua b/etc/b64.lua deleted file mode 100644 index 11eeb2d..0000000 --- a/etc/b64.lua +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- Little program to convert to and from Base64 | ||
3 | -- LuaSocket sample files | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | local ltn12 = require("ltn12") | ||
7 | local mime = require("mime") | ||
8 | local source = ltn12.source.file(io.stdin) | ||
9 | local sink = ltn12.sink.file(io.stdout) | ||
10 | local convert | ||
11 | if arg and arg[1] == '-d' then | ||
12 | convert = mime.decode("base64") | ||
13 | else | ||
14 | local base64 = mime.encode("base64") | ||
15 | local wrap = mime.wrap() | ||
16 | convert = ltn12.filter.chain(base64, wrap) | ||
17 | end | ||
18 | sink = ltn12.sink.chain(convert, sink) | ||
19 | ltn12.pump.all(source, sink) | ||
diff --git a/etc/check-links.lua b/etc/check-links.lua deleted file mode 100644 index 283f3ac..0000000 --- a/etc/check-links.lua +++ /dev/null | |||
@@ -1,111 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- Little program that checks links in HTML files, using coroutines and | ||
3 | -- non-blocking I/O via the dispatcher module. | ||
4 | -- LuaSocket sample files | ||
5 | -- Author: Diego Nehab | ||
6 | ----------------------------------------------------------------------------- | ||
7 | local url = require("socket.url") | ||
8 | local dispatch = require("dispatch") | ||
9 | local http = require("socket.http") | ||
10 | dispatch.TIMEOUT = 10 | ||
11 | |||
12 | -- make sure the user knows how to invoke us | ||
13 | arg = arg or {} | ||
14 | if #arg < 1 then | ||
15 | print("Usage:\n luasocket check-links.lua [-n] {<url>}") | ||
16 | exit() | ||
17 | end | ||
18 | |||
19 | -- '-n' means we are running in non-blocking mode | ||
20 | if arg[1] == "-n" then | ||
21 | -- if non-blocking I/O was requested, use real dispatcher interface | ||
22 | table.remove(arg, 1) | ||
23 | handler = dispatch.newhandler("coroutine") | ||
24 | else | ||
25 | -- if using blocking I/O, use fake dispatcher interface | ||
26 | handler = dispatch.newhandler("sequential") | ||
27 | end | ||
28 | |||
29 | local nthreads = 0 | ||
30 | |||
31 | -- get the status of a URL using the dispatcher | ||
32 | function getstatus(link) | ||
33 | local parsed = url.parse(link, {scheme = "file"}) | ||
34 | if parsed.scheme == "http" then | ||
35 | nthreads = nthreads + 1 | ||
36 | handler:start(function() | ||
37 | local r, c, h, s = http.request{ | ||
38 | method = "HEAD", | ||
39 | url = link, | ||
40 | create = handler.tcp | ||
41 | } | ||
42 | if r and c == 200 then io.write('\t', link, '\n') | ||
43 | else io.write('\t', link, ': ', tostring(c), '\n') end | ||
44 | nthreads = nthreads - 1 | ||
45 | end) | ||
46 | end | ||
47 | end | ||
48 | |||
49 | function readfile(path) | ||
50 | path = url.unescape(path) | ||
51 | local file, error = io.open(path, "r") | ||
52 | if file then | ||
53 | local body = file:read("*a") | ||
54 | file:close() | ||
55 | return body | ||
56 | else return nil, error end | ||
57 | end | ||
58 | |||
59 | function load(u) | ||
60 | local parsed = url.parse(u, { scheme = "file" }) | ||
61 | local body, headers, code, error | ||
62 | local base = u | ||
63 | if parsed.scheme == "http" then | ||
64 | body, code, headers = http.request(u) | ||
65 | if code == 200 then | ||
66 | -- if there was a redirect, update base to reflect it | ||
67 | base = headers.location or base | ||
68 | end | ||
69 | if not body then | ||
70 | error = code | ||
71 | end | ||
72 | elseif parsed.scheme == "file" then | ||
73 | body, error = readfile(parsed.path) | ||
74 | else error = string.format("unhandled scheme '%s'", parsed.scheme) end | ||
75 | return base, body, error | ||
76 | end | ||
77 | |||
78 | function getlinks(body, base) | ||
79 | -- get rid of comments | ||
80 | body = string.gsub(body, "%<%!%-%-.-%-%-%>", "") | ||
81 | local links = {} | ||
82 | -- extract links | ||
83 | body = string.gsub(body, '[Hh][Rr][Ee][Ff]%s*=%s*"([^"]*)"', function(href) | ||
84 | table.insert(links, url.absolute(base, href)) | ||
85 | end) | ||
86 | body = string.gsub(body, "[Hh][Rr][Ee][Ff]%s*=%s*'([^']*)'", function(href) | ||
87 | table.insert(links, url.absolute(base, href)) | ||
88 | end) | ||
89 | string.gsub(body, "[Hh][Rr][Ee][Ff]%s*=%s*(.-)>", function(href) | ||
90 | table.insert(links, url.absolute(base, href)) | ||
91 | end) | ||
92 | return links | ||
93 | end | ||
94 | |||
95 | function checklinks(address) | ||
96 | local base, body, error = load(address) | ||
97 | if not body then print(error) return end | ||
98 | print("Checking ", base) | ||
99 | local links = getlinks(body, base) | ||
100 | for _, link in ipairs(links) do | ||
101 | getstatus(link) | ||
102 | end | ||
103 | end | ||
104 | |||
105 | for _, address in ipairs(arg) do | ||
106 | checklinks(url.absolute("file:", address)) | ||
107 | end | ||
108 | |||
109 | while nthreads > 0 do | ||
110 | handler:step() | ||
111 | end | ||
diff --git a/etc/check-memory.lua b/etc/check-memory.lua deleted file mode 100644 index 7bd984d..0000000 --- a/etc/check-memory.lua +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | function load(s) | ||
2 | collectgarbage() | ||
3 | local a = gcinfo() | ||
4 | _G[s] = require(s) | ||
5 | collectgarbage() | ||
6 | local b = gcinfo() | ||
7 | print(s .. ":\t " .. (b-a) .. "k") | ||
8 | end | ||
9 | |||
10 | load("socket.url") | ||
11 | load("ltn12") | ||
12 | load("socket") | ||
13 | load("mime") | ||
14 | load("socket.tp") | ||
15 | load("socket.smtp") | ||
16 | load("socket.http") | ||
17 | load("socket.ftp") | ||
diff --git a/etc/cookie.lua b/etc/cookie.lua deleted file mode 100644 index 4adb403..0000000 --- a/etc/cookie.lua +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | local socket = require"socket" | ||
2 | local http = require"socket.http" | ||
3 | local url = require"socket.url" | ||
4 | local ltn12 = require"ltn12" | ||
5 | |||
6 | local token_class = '[^%c%s%(%)%<%>%@%,%;%:%\\%"%/%[%]%?%=%{%}]' | ||
7 | |||
8 | local function unquote(t, quoted) | ||
9 | local n = string.match(t, "%$(%d+)$") | ||
10 | if n then n = tonumber(n) end | ||
11 | if quoted[n] then return quoted[n] | ||
12 | else return t end | ||
13 | end | ||
14 | |||
15 | local function parse_set_cookie(c, quoted, cookie_table) | ||
16 | c = c .. ";$last=last;" | ||
17 | local _, __, n, v, i = string.find(c, "(" .. token_class .. | ||
18 | "+)%s*=%s*(.-)%s*;%s*()") | ||
19 | local cookie = { | ||
20 | name = n, | ||
21 | value = unquote(v, quoted), | ||
22 | attributes = {} | ||
23 | } | ||
24 | while 1 do | ||
25 | _, __, n, v, i = string.find(c, "(" .. token_class .. | ||
26 | "+)%s*=?%s*(.-)%s*;%s*()", i) | ||
27 | if not n or n == "$last" then break end | ||
28 | cookie.attributes[#cookie.attributes+1] = { | ||
29 | name = n, | ||
30 | value = unquote(v, quoted) | ||
31 | } | ||
32 | end | ||
33 | cookie_table[#cookie_table+1] = cookie | ||
34 | end | ||
35 | |||
36 | local function split_set_cookie(s, cookie_table) | ||
37 | cookie_table = cookie_table or {} | ||
38 | -- remove quoted strings from cookie list | ||
39 | local quoted = {} | ||
40 | s = string.gsub(s, '"(.-)"', function(q) | ||
41 | quoted[#quoted+1] = q | ||
42 | return "$" .. #quoted | ||
43 | end) | ||
44 | -- add sentinel | ||
45 | s = s .. ",$last=" | ||
46 | -- split into individual cookies | ||
47 | i = 1 | ||
48 | while 1 do | ||
49 | local _, __, cookie, next_token | ||
50 | _, __, cookie, i, next_token = string.find(s, "(.-)%s*%,%s*()(" .. | ||
51 | token_class .. "+)%s*=", i) | ||
52 | if not next_token then break end | ||
53 | parse_set_cookie(cookie, quoted, cookie_table) | ||
54 | if next_token == "$last" then break end | ||
55 | end | ||
56 | return cookie_table | ||
57 | end | ||
58 | |||
59 | local function quote(s) | ||
60 | if string.find(s, "[ %,%;]") then return '"' .. s .. '"' | ||
61 | else return s end | ||
62 | end | ||
63 | |||
64 | local _empty = {} | ||
65 | local function build_cookies(cookies) | ||
66 | s = "" | ||
67 | for i,v in ipairs(cookies or _empty) do | ||
68 | if v.name then | ||
69 | s = s .. v.name | ||
70 | if v.value and v.value ~= "" then | ||
71 | s = s .. '=' .. quote(v.value) | ||
72 | end | ||
73 | end | ||
74 | if v.name and #(v.attributes or _empty) > 0 then s = s .. "; " end | ||
75 | for j,u in ipairs(v.attributes or _empty) do | ||
76 | if u.name then | ||
77 | s = s .. u.name | ||
78 | if u.value and u.value ~= "" then | ||
79 | s = s .. '=' .. quote(u.value) | ||
80 | end | ||
81 | end | ||
82 | if j < #v.attributes then s = s .. "; " end | ||
83 | end | ||
84 | if i < #cookies then s = s .. ", " end | ||
85 | end | ||
86 | return s | ||
87 | end | ||
88 | |||
diff --git a/etc/dict.lua b/etc/dict.lua deleted file mode 100644 index 8c5b711..0000000 --- a/etc/dict.lua +++ /dev/null | |||
@@ -1,151 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- Little program to download DICT word definitions | ||
3 | -- LuaSocket sample files | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Load required modules | ||
9 | ----------------------------------------------------------------------------- | ||
10 | local base = _G | ||
11 | local string = require("string") | ||
12 | local table = require("table") | ||
13 | local socket = require("socket") | ||
14 | local url = require("socket.url") | ||
15 | local tp = require("socket.tp") | ||
16 | module("socket.dict") | ||
17 | |||
18 | ----------------------------------------------------------------------------- | ||
19 | -- Globals | ||
20 | ----------------------------------------------------------------------------- | ||
21 | HOST = "dict.org" | ||
22 | PORT = 2628 | ||
23 | TIMEOUT = 10 | ||
24 | |||
25 | ----------------------------------------------------------------------------- | ||
26 | -- Low-level dict API | ||
27 | ----------------------------------------------------------------------------- | ||
28 | local metat = { __index = {} } | ||
29 | |||
30 | function open(host, port) | ||
31 | local tp = socket.try(tp.connect(host or HOST, port or PORT, TIMEOUT)) | ||
32 | return base.setmetatable({tp = tp}, metat) | ||
33 | end | ||
34 | |||
35 | function metat.__index:greet() | ||
36 | return socket.try(self.tp:check(220)) | ||
37 | end | ||
38 | |||
39 | function metat.__index:check(ok) | ||
40 | local code, status = socket.try(self.tp:check(ok)) | ||
41 | return code, | ||
42 | base.tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)"))) | ||
43 | end | ||
44 | |||
45 | function metat.__index:getdef() | ||
46 | local line = socket.try(self.tp:receive()) | ||
47 | local def = {} | ||
48 | while line ~= "." do | ||
49 | table.insert(def, line) | ||
50 | line = socket.try(self.tp:receive()) | ||
51 | end | ||
52 | return table.concat(def, "\n") | ||
53 | end | ||
54 | |||
55 | function metat.__index:define(database, word) | ||
56 | database = database or "!" | ||
57 | socket.try(self.tp:command("DEFINE", database .. " " .. word)) | ||
58 | local code, count = self:check(150) | ||
59 | local defs = {} | ||
60 | for i = 1, count do | ||
61 | self:check(151) | ||
62 | table.insert(defs, self:getdef()) | ||
63 | end | ||
64 | self:check(250) | ||
65 | return defs | ||
66 | end | ||
67 | |||
68 | function metat.__index:match(database, strat, word) | ||
69 | database = database or "!" | ||
70 | strat = strat or "." | ||
71 | socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word)) | ||
72 | self:check(152) | ||
73 | local mat = {} | ||
74 | local line = socket.try(self.tp:receive()) | ||
75 | while line ~= '.' do | ||
76 | database, word = socket.skip(2, string.find(line, "(%S+) (.*)")) | ||
77 | if not mat[database] then mat[database] = {} end | ||
78 | table.insert(mat[database], word) | ||
79 | line = socket.try(self.tp:receive()) | ||
80 | end | ||
81 | self:check(250) | ||
82 | return mat | ||
83 | end | ||
84 | |||
85 | function metat.__index:quit() | ||
86 | self.tp:command("QUIT") | ||
87 | return self:check(221) | ||
88 | end | ||
89 | |||
90 | function metat.__index:close() | ||
91 | return self.tp:close() | ||
92 | end | ||
93 | |||
94 | ----------------------------------------------------------------------------- | ||
95 | -- High-level dict API | ||
96 | ----------------------------------------------------------------------------- | ||
97 | local default = { | ||
98 | scheme = "dict", | ||
99 | host = "dict.org" | ||
100 | } | ||
101 | |||
102 | local function there(f) | ||
103 | if f == "" then return nil | ||
104 | else return f end | ||
105 | end | ||
106 | |||
107 | local function parse(u) | ||
108 | local t = socket.try(url.parse(u, default)) | ||
109 | socket.try(t.scheme == "dict", "invalid scheme '" .. t.scheme .. "'") | ||
110 | socket.try(t.path, "invalid path in url") | ||
111 | local cmd, arg = socket.skip(2, string.find(t.path, "^/(.)(.*)$")) | ||
112 | socket.try(cmd == "d" or cmd == "m", "<command> should be 'm' or 'd'") | ||
113 | socket.try(arg and arg ~= "", "need at least <word> in URL") | ||
114 | t.command, t.argument = cmd, arg | ||
115 | arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end) | ||
116 | socket.try(t.word, "need at least <word> in URL") | ||
117 | arg = string.gsub(arg, "^:([^:]*)", function(f) t.database = there(f) end) | ||
118 | if cmd == "m" then | ||
119 | arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end) | ||
120 | end | ||
121 | string.gsub(arg, ":([^:]*)$", function(f) t.n = base.tonumber(f) end) | ||
122 | return t | ||
123 | end | ||
124 | |||
125 | local function tget(gett) | ||
126 | local con = open(gett.host, gett.port) | ||
127 | con:greet() | ||
128 | if gett.command == "d" then | ||
129 | local def = con:define(gett.database, gett.word) | ||
130 | con:quit() | ||
131 | con:close() | ||
132 | if gett.n then return def[gett.n] | ||
133 | else return def end | ||
134 | elseif gett.command == "m" then | ||
135 | local mat = con:match(gett.database, gett.strat, gett.word) | ||
136 | con:quit() | ||
137 | con:close() | ||
138 | return mat | ||
139 | else return nil, "invalid command" end | ||
140 | end | ||
141 | |||
142 | local function sget(u) | ||
143 | local gett = parse(u) | ||
144 | return tget(gett) | ||
145 | end | ||
146 | |||
147 | get = socket.protect(function(gett) | ||
148 | if base.type(gett) == "string" then return sget(gett) | ||
149 | else return tget(gett) end | ||
150 | end) | ||
151 | |||
diff --git a/etc/dispatch.lua b/etc/dispatch.lua deleted file mode 100644 index 2485415..0000000 --- a/etc/dispatch.lua +++ /dev/null | |||
@@ -1,307 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- A hacked dispatcher module | ||
3 | -- LuaSocket sample files | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | local base = _G | ||
7 | local table = require("table") | ||
8 | local string = require("string") | ||
9 | local socket = require("socket") | ||
10 | local coroutine = require("coroutine") | ||
11 | module("dispatch") | ||
12 | |||
13 | -- if too much time goes by without any activity in one of our sockets, we | ||
14 | -- just kill it | ||
15 | TIMEOUT = 60 | ||
16 | |||
17 | ----------------------------------------------------------------------------- | ||
18 | -- We implement 3 types of dispatchers: | ||
19 | -- sequential | ||
20 | -- coroutine | ||
21 | -- threaded | ||
22 | -- The user can choose whatever one is needed | ||
23 | ----------------------------------------------------------------------------- | ||
24 | local handlert = {} | ||
25 | |||
26 | -- default handler is coroutine | ||
27 | function newhandler(mode) | ||
28 | mode = mode or "coroutine" | ||
29 | return handlert[mode]() | ||
30 | end | ||
31 | |||
32 | local function seqstart(self, func) | ||
33 | return func() | ||
34 | end | ||
35 | |||
36 | -- sequential handler simply calls the functions and doesn't wrap I/O | ||
37 | function handlert.sequential() | ||
38 | return { | ||
39 | tcp = socket.tcp, | ||
40 | start = seqstart | ||
41 | } | ||
42 | end | ||
43 | |||
44 | ----------------------------------------------------------------------------- | ||
45 | -- Mega hack. Don't try to do this at home. | ||
46 | ----------------------------------------------------------------------------- | ||
47 | -- we can't yield across calls to protect on Lua 5.1, so we rewrite it with | ||
48 | -- coroutines | ||
49 | -- make sure you don't require any module that uses socket.protect before | ||
50 | -- loading our hack | ||
51 | if string.sub(base._VERSION, -3) == "5.1" then | ||
52 | local function _protect(co, status, ...) | ||
53 | if not status then | ||
54 | local msg = ... | ||
55 | if base.type(msg) == 'table' then | ||
56 | return nil, msg[1] | ||
57 | else | ||
58 | base.error(msg, 0) | ||
59 | end | ||
60 | end | ||
61 | if coroutine.status(co) == "suspended" then | ||
62 | return _protect(co, coroutine.resume(co, coroutine.yield(...))) | ||
63 | else | ||
64 | return ... | ||
65 | end | ||
66 | end | ||
67 | |||
68 | function socket.protect(f) | ||
69 | return function(...) | ||
70 | local co = coroutine.create(f) | ||
71 | return _protect(co, coroutine.resume(co, ...)) | ||
72 | end | ||
73 | end | ||
74 | end | ||
75 | |||
76 | ----------------------------------------------------------------------------- | ||
77 | -- Simple set data structure. O(1) everything. | ||
78 | ----------------------------------------------------------------------------- | ||
79 | local function newset() | ||
80 | local reverse = {} | ||
81 | local set = {} | ||
82 | return base.setmetatable(set, {__index = { | ||
83 | insert = function(set, value) | ||
84 | if not reverse[value] then | ||
85 | table.insert(set, value) | ||
86 | reverse[value] = #set | ||
87 | end | ||
88 | end, | ||
89 | remove = function(set, value) | ||
90 | local index = reverse[value] | ||
91 | if index then | ||
92 | reverse[value] = nil | ||
93 | local top = table.remove(set) | ||
94 | if top ~= value then | ||
95 | reverse[top] = index | ||
96 | set[index] = top | ||
97 | end | ||
98 | end | ||
99 | end | ||
100 | }}) | ||
101 | end | ||
102 | |||
103 | ----------------------------------------------------------------------------- | ||
104 | -- socket.tcp() wrapper for the coroutine dispatcher | ||
105 | ----------------------------------------------------------------------------- | ||
106 | local function cowrap(dispatcher, tcp, error) | ||
107 | if not tcp then return nil, error end | ||
108 | -- put it in non-blocking mode right away | ||
109 | tcp:settimeout(0) | ||
110 | -- metatable for wrap produces new methods on demand for those that we | ||
111 | -- don't override explicitly. | ||
112 | local metat = { __index = function(table, key) | ||
113 | table[key] = function(...) | ||
114 | return tcp[key](tcp,select(2,...)) | ||
115 | end | ||
116 | return table[key] | ||
117 | end} | ||
118 | -- does our user want to do his own non-blocking I/O? | ||
119 | local zero = false | ||
120 | -- create a wrap object that will behave just like a real socket object | ||
121 | local wrap = { } | ||
122 | -- we ignore settimeout to preserve our 0 timeout, but record whether | ||
123 | -- the user wants to do his own non-blocking I/O | ||
124 | function wrap:settimeout(value, mode) | ||
125 | if value == 0 then zero = true | ||
126 | else zero = false end | ||
127 | return 1 | ||
128 | end | ||
129 | -- send in non-blocking mode and yield on timeout | ||
130 | function wrap:send(data, first, last) | ||
131 | first = (first or 1) - 1 | ||
132 | local result, error | ||
133 | while true do | ||
134 | -- return control to dispatcher and tell it we want to send | ||
135 | -- if upon return the dispatcher tells us we timed out, | ||
136 | -- return an error to whoever called us | ||
137 | if coroutine.yield(dispatcher.sending, tcp) == "timeout" then | ||
138 | return nil, "timeout" | ||
139 | end | ||
140 | -- try sending | ||
141 | result, error, first = tcp:send(data, first+1, last) | ||
142 | -- if we are done, or there was an unexpected error, | ||
143 | -- break away from loop | ||
144 | if error ~= "timeout" then return result, error, first end | ||
145 | end | ||
146 | end | ||
147 | -- receive in non-blocking mode and yield on timeout | ||
148 | -- or simply return partial read, if user requested timeout = 0 | ||
149 | function wrap:receive(pattern, partial) | ||
150 | local error = "timeout" | ||
151 | local value | ||
152 | while true do | ||
153 | -- return control to dispatcher and tell it we want to receive | ||
154 | -- if upon return the dispatcher tells us we timed out, | ||
155 | -- return an error to whoever called us | ||
156 | if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then | ||
157 | return nil, "timeout" | ||
158 | end | ||
159 | -- try receiving | ||
160 | value, error, partial = tcp:receive(pattern, partial) | ||
161 | -- if we are done, or there was an unexpected error, | ||
162 | -- break away from loop. also, if the user requested | ||
163 | -- zero timeout, return all we got | ||
164 | if (error ~= "timeout") or zero then | ||
165 | return value, error, partial | ||
166 | end | ||
167 | end | ||
168 | end | ||
169 | -- connect in non-blocking mode and yield on timeout | ||
170 | function wrap:connect(host, port) | ||
171 | local result, error = tcp:connect(host, port) | ||
172 | if error == "timeout" then | ||
173 | -- return control to dispatcher. we will be writable when | ||
174 | -- connection succeeds. | ||
175 | -- if upon return the dispatcher tells us we have a | ||
176 | -- timeout, just abort | ||
177 | if coroutine.yield(dispatcher.sending, tcp) == "timeout" then | ||
178 | return nil, "timeout" | ||
179 | end | ||
180 | -- when we come back, check if connection was successful | ||
181 | result, error = tcp:connect(host, port) | ||
182 | if result or error == "already connected" then return 1 | ||
183 | else return nil, "non-blocking connect failed" end | ||
184 | else return result, error end | ||
185 | end | ||
186 | -- accept in non-blocking mode and yield on timeout | ||
187 | function wrap:accept() | ||
188 | while 1 do | ||
189 | -- return control to dispatcher. we will be readable when a | ||
190 | -- connection arrives. | ||
191 | -- if upon return the dispatcher tells us we have a | ||
192 | -- timeout, just abort | ||
193 | if coroutine.yield(dispatcher.receiving, tcp) == "timeout" then | ||
194 | return nil, "timeout" | ||
195 | end | ||
196 | local client, error = tcp:accept() | ||
197 | if error ~= "timeout" then | ||
198 | return cowrap(dispatcher, client, error) | ||
199 | end | ||
200 | end | ||
201 | end | ||
202 | -- remove cortn from context | ||
203 | function wrap:close() | ||
204 | dispatcher.stamp[tcp] = nil | ||
205 | dispatcher.sending.set:remove(tcp) | ||
206 | dispatcher.sending.cortn[tcp] = nil | ||
207 | dispatcher.receiving.set:remove(tcp) | ||
208 | dispatcher.receiving.cortn[tcp] = nil | ||
209 | return tcp:close() | ||
210 | end | ||
211 | return base.setmetatable(wrap, metat) | ||
212 | end | ||
213 | |||
214 | |||
215 | ----------------------------------------------------------------------------- | ||
216 | -- Our coroutine dispatcher | ||
217 | ----------------------------------------------------------------------------- | ||
218 | local cometat = { __index = {} } | ||
219 | |||
220 | function schedule(cortn, status, operation, tcp) | ||
221 | if status then | ||
222 | if cortn and operation then | ||
223 | operation.set:insert(tcp) | ||
224 | operation.cortn[tcp] = cortn | ||
225 | operation.stamp[tcp] = socket.gettime() | ||
226 | end | ||
227 | else base.error(operation) end | ||
228 | end | ||
229 | |||
230 | function kick(operation, tcp) | ||
231 | operation.cortn[tcp] = nil | ||
232 | operation.set:remove(tcp) | ||
233 | end | ||
234 | |||
235 | function wakeup(operation, tcp) | ||
236 | local cortn = operation.cortn[tcp] | ||
237 | -- if cortn is still valid, wake it up | ||
238 | if cortn then | ||
239 | kick(operation, tcp) | ||
240 | return cortn, coroutine.resume(cortn) | ||
241 | -- othrewise, just get scheduler not to do anything | ||
242 | else | ||
243 | return nil, true | ||
244 | end | ||
245 | end | ||
246 | |||
247 | function abort(operation, tcp) | ||
248 | local cortn = operation.cortn[tcp] | ||
249 | if cortn then | ||
250 | kick(operation, tcp) | ||
251 | coroutine.resume(cortn, "timeout") | ||
252 | end | ||
253 | end | ||
254 | |||
255 | -- step through all active cortns | ||
256 | function cometat.__index:step() | ||
257 | -- check which sockets are interesting and act on them | ||
258 | local readable, writable = socket.select(self.receiving.set, | ||
259 | self.sending.set, 1) | ||
260 | -- for all readable connections, resume their cortns and reschedule | ||
261 | -- when they yield back to us | ||
262 | for _, tcp in base.ipairs(readable) do | ||
263 | schedule(wakeup(self.receiving, tcp)) | ||
264 | end | ||
265 | -- for all writable connections, do the same | ||
266 | for _, tcp in base.ipairs(writable) do | ||
267 | schedule(wakeup(self.sending, tcp)) | ||
268 | end | ||
269 | -- politely ask replacement I/O functions in idle cortns to | ||
270 | -- return reporting a timeout | ||
271 | local now = socket.gettime() | ||
272 | for tcp, stamp in base.pairs(self.stamp) do | ||
273 | if tcp.class == "tcp{client}" and now - stamp > TIMEOUT then | ||
274 | abort(self.sending, tcp) | ||
275 | abort(self.receiving, tcp) | ||
276 | end | ||
277 | end | ||
278 | end | ||
279 | |||
280 | function cometat.__index:start(func) | ||
281 | local cortn = coroutine.create(func) | ||
282 | schedule(cortn, coroutine.resume(cortn)) | ||
283 | end | ||
284 | |||
285 | function handlert.coroutine() | ||
286 | local stamp = {} | ||
287 | local dispatcher = { | ||
288 | stamp = stamp, | ||
289 | sending = { | ||
290 | name = "sending", | ||
291 | set = newset(), | ||
292 | cortn = {}, | ||
293 | stamp = stamp | ||
294 | }, | ||
295 | receiving = { | ||
296 | name = "receiving", | ||
297 | set = newset(), | ||
298 | cortn = {}, | ||
299 | stamp = stamp | ||
300 | }, | ||
301 | } | ||
302 | function dispatcher.tcp() | ||
303 | return cowrap(dispatcher, socket.tcp()) | ||
304 | end | ||
305 | return base.setmetatable(dispatcher, cometat) | ||
306 | end | ||
307 | |||
diff --git a/etc/eol.lua b/etc/eol.lua deleted file mode 100644 index eeaf0ce..0000000 --- a/etc/eol.lua +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- Little program to adjust end of line markers. | ||
3 | -- LuaSocket sample files | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | local mime = require("mime") | ||
7 | local ltn12 = require("ltn12") | ||
8 | local marker = '\n' | ||
9 | if arg and arg[1] == '-d' then marker = '\r\n' end | ||
10 | local filter = mime.normalize(marker) | ||
11 | local source = ltn12.source.chain(ltn12.source.file(io.stdin), filter) | ||
12 | local sink = ltn12.sink.file(io.stdout) | ||
13 | ltn12.pump.all(source, sink) | ||
diff --git a/etc/forward.lua b/etc/forward.lua deleted file mode 100644 index 05ced1a..0000000 --- a/etc/forward.lua +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | -- load our favourite library | ||
2 | local dispatch = require("dispatch") | ||
3 | local handler = dispatch.newhandler() | ||
4 | |||
5 | -- make sure the user knows how to invoke us | ||
6 | if #arg < 1 then | ||
7 | print("Usage") | ||
8 | print(" lua forward.lua <iport:ohost:oport> ...") | ||
9 | os.exit(1) | ||
10 | end | ||
11 | |||
12 | -- function to move data from one socket to the other | ||
13 | local function move(foo, bar) | ||
14 | local live | ||
15 | while 1 do | ||
16 | local data, error, partial = foo:receive(2048) | ||
17 | live = data or error == "timeout" | ||
18 | data = data or partial | ||
19 | local result, error = bar:send(data) | ||
20 | if not live or not result then | ||
21 | foo:close() | ||
22 | bar:close() | ||
23 | break | ||
24 | end | ||
25 | end | ||
26 | end | ||
27 | |||
28 | -- for each tunnel, start a new server | ||
29 | for i, v in ipairs(arg) do | ||
30 | -- capture forwarding parameters | ||
31 | local _, _, iport, ohost, oport = string.find(v, "([^:]+):([^:]+):([^:]+)") | ||
32 | assert(iport, "invalid arguments") | ||
33 | -- create our server socket | ||
34 | local server = assert(handler.tcp()) | ||
35 | assert(server:setoption("reuseaddr", true)) | ||
36 | assert(server:bind("*", iport)) | ||
37 | assert(server:listen(32)) | ||
38 | -- handler for the server object loops accepting new connections | ||
39 | handler:start(function() | ||
40 | while 1 do | ||
41 | local client = assert(server:accept()) | ||
42 | assert(client:settimeout(0)) | ||
43 | -- for each new connection, start a new client handler | ||
44 | handler:start(function() | ||
45 | -- handler tries to connect to peer | ||
46 | local peer = assert(handler.tcp()) | ||
47 | assert(peer:settimeout(0)) | ||
48 | assert(peer:connect(ohost, oport)) | ||
49 | -- if sucessful, starts a new handler to send data from | ||
50 | -- client to peer | ||
51 | handler:start(function() | ||
52 | move(client, peer) | ||
53 | end) | ||
54 | -- afte starting new handler, enter in loop sending data from | ||
55 | -- peer to client | ||
56 | move(peer, client) | ||
57 | end) | ||
58 | end | ||
59 | end) | ||
60 | end | ||
61 | |||
62 | -- simply loop stepping the server | ||
63 | while 1 do | ||
64 | handler:step() | ||
65 | end | ||
diff --git a/etc/get.lua b/etc/get.lua deleted file mode 100644 index 9edc235..0000000 --- a/etc/get.lua +++ /dev/null | |||
@@ -1,141 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- Little program to download files from URLs | ||
3 | -- LuaSocket sample files | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | local socket = require("socket") | ||
7 | local http = require("socket.http") | ||
8 | local ftp = require("socket.ftp") | ||
9 | local url = require("socket.url") | ||
10 | local ltn12 = require("ltn12") | ||
11 | |||
12 | -- formats a number of seconds into human readable form | ||
13 | function nicetime(s) | ||
14 | local l = "s" | ||
15 | if s > 60 then | ||
16 | s = s / 60 | ||
17 | l = "m" | ||
18 | if s > 60 then | ||
19 | s = s / 60 | ||
20 | l = "h" | ||
21 | if s > 24 then | ||
22 | s = s / 24 | ||
23 | l = "d" -- hmmm | ||
24 | end | ||
25 | end | ||
26 | end | ||
27 | if l == "s" then return string.format("%5.0f%s", s, l) | ||
28 | else return string.format("%5.2f%s", s, l) end | ||
29 | end | ||
30 | |||
31 | -- formats a number of bytes into human readable form | ||
32 | function nicesize(b) | ||
33 | local l = "B" | ||
34 | if b > 1024 then | ||
35 | b = b / 1024 | ||
36 | l = "KB" | ||
37 | if b > 1024 then | ||
38 | b = b / 1024 | ||
39 | l = "MB" | ||
40 | if b > 1024 then | ||
41 | b = b / 1024 | ||
42 | l = "GB" -- hmmm | ||
43 | end | ||
44 | end | ||
45 | end | ||
46 | return string.format("%7.2f%2s", b, l) | ||
47 | end | ||
48 | |||
49 | -- returns a string with the current state of the download | ||
50 | local remaining_s = "%s received, %s/s throughput, %2.0f%% done, %s remaining" | ||
51 | local elapsed_s = "%s received, %s/s throughput, %s elapsed " | ||
52 | function gauge(got, delta, size) | ||
53 | local rate = got / delta | ||
54 | if size and size >= 1 then | ||
55 | return string.format(remaining_s, nicesize(got), nicesize(rate), | ||
56 | 100*got/size, nicetime((size-got)/rate)) | ||
57 | else | ||
58 | return string.format(elapsed_s, nicesize(got), | ||
59 | nicesize(rate), nicetime(delta)) | ||
60 | end | ||
61 | end | ||
62 | |||
63 | -- creates a new instance of a receive_cb that saves to disk | ||
64 | -- kind of copied from luasocket's manual callback examples | ||
65 | function stats(size) | ||
66 | local start = socket.gettime() | ||
67 | local last = start | ||
68 | local got = 0 | ||
69 | return function(chunk) | ||
70 | -- elapsed time since start | ||
71 | local current = socket.gettime() | ||
72 | if chunk then | ||
73 | -- total bytes received | ||
74 | got = got + string.len(chunk) | ||
75 | -- not enough time for estimate | ||
76 | if current - last > 1 then | ||
77 | io.stderr:write("\r", gauge(got, current - start, size)) | ||
78 | io.stderr:flush() | ||
79 | last = current | ||
80 | end | ||
81 | else | ||
82 | -- close up | ||
83 | io.stderr:write("\r", gauge(got, current - start), "\n") | ||
84 | end | ||
85 | return chunk | ||
86 | end | ||
87 | end | ||
88 | |||
89 | -- determines the size of a http file | ||
90 | function gethttpsize(u) | ||
91 | local r, c, h = http.request {method = "HEAD", url = u} | ||
92 | if c == 200 then | ||
93 | return tonumber(h["content-length"]) | ||
94 | end | ||
95 | end | ||
96 | |||
97 | -- downloads a file using the http protocol | ||
98 | function getbyhttp(u, file) | ||
99 | local save = ltn12.sink.file(file or io.stdout) | ||
100 | -- only print feedback if output is not stdout | ||
101 | if file then save = ltn12.sink.chain(stats(gethttpsize(u)), save) end | ||
102 | local r, c, h, s = http.request {url = u, sink = save } | ||
103 | if c ~= 200 then io.stderr:write(s or c, "\n") end | ||
104 | end | ||
105 | |||
106 | -- downloads a file using the ftp protocol | ||
107 | function getbyftp(u, file) | ||
108 | local save = ltn12.sink.file(file or io.stdout) | ||
109 | -- only print feedback if output is not stdout | ||
110 | -- and we don't know how big the file is | ||
111 | if file then save = ltn12.sink.chain(stats(), save) end | ||
112 | local gett = url.parse(u) | ||
113 | gett.sink = save | ||
114 | gett.type = "i" | ||
115 | local ret, err = ftp.get(gett) | ||
116 | if err then print(err) end | ||
117 | end | ||
118 | |||
119 | -- determines the scheme | ||
120 | function getscheme(u) | ||
121 | -- this is an heuristic to solve a common invalid url poblem | ||
122 | if not string.find(u, "//") then u = "//" .. u end | ||
123 | local parsed = url.parse(u, {scheme = "http"}) | ||
124 | return parsed.scheme | ||
125 | end | ||
126 | |||
127 | -- gets a file either by http or ftp, saving as <name> | ||
128 | function get(u, name) | ||
129 | local fout = name and io.open(name, "wb") | ||
130 | local scheme = getscheme(u) | ||
131 | if scheme == "ftp" then getbyftp(u, fout) | ||
132 | elseif scheme == "http" then getbyhttp(u, fout) | ||
133 | else print("unknown scheme" .. scheme) end | ||
134 | end | ||
135 | |||
136 | -- main program | ||
137 | arg = arg or {} | ||
138 | if #arg < 1 then | ||
139 | io.write("Usage:\n lua get.lua <remote-url> [<local-file>]\n") | ||
140 | os.exit(1) | ||
141 | else get(arg[1], arg[2]) end | ||
diff --git a/etc/links b/etc/links deleted file mode 100644 index 087f1c0..0000000 --- a/etc/links +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | <a href="http://www.cs.princeton.edu"> bla </a> | ||
2 | <a href="http://www.princeton.edu"> bla </a> | ||
3 | <a href="http://www.tecgraf.puc-rio.br"> bla </a> | ||
4 | <a href="http://www.inf.puc-rio.br"> bla </a> | ||
5 | <a href="http://www.puc-rio.br"> bla </a> | ||
6 | <a href="http://www.impa.br"> bla </a> | ||
7 | <a href="http://www.lua.org"> bla </a> | ||
8 | <a href="http://www.lua-users.org"> bla </a> | ||
9 | <a href="http://www.amazon.com"> bla </a> | ||
10 | <a href="http://www.google.com"> bla </a> | ||
11 | <a href="http://www.nytimes.com"> bla </a> | ||
12 | <a href="http://www.bbc.co.uk"> bla </a> | ||
13 | <a href="http://oglobo.globo.com"> bla </a> | ||
14 | <a href="http://slate.msn.com"> bla </a> | ||
15 | <a href="http://www.apple.com"> bla </a> | ||
16 | <a href="http://www.microsoft.com"> bla </a> | ||
17 | <a href="http://www.nasa.gov"> bla </a> | ||
diff --git a/etc/lp.lua b/etc/lp.lua deleted file mode 100644 index 25f0b95..0000000 --- a/etc/lp.lua +++ /dev/null | |||
@@ -1,323 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- LPD support for the Lua language | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: David Burgess | ||
5 | -- Modified by Diego Nehab, but David is in charge | ||
6 | ----------------------------------------------------------------------------- | ||
7 | --[[ | ||
8 | if you have any questions: RFC 1179 | ||
9 | ]] | ||
10 | -- make sure LuaSocket is loaded | ||
11 | local io = require("io") | ||
12 | local base = _G | ||
13 | local os = require("os") | ||
14 | local math = require("math") | ||
15 | local string = require("string") | ||
16 | local socket = require("socket") | ||
17 | local ltn12 = require("ltn12") | ||
18 | module("socket.lp") | ||
19 | |||
20 | -- default port | ||
21 | PORT = 515 | ||
22 | SERVER = os.getenv("SERVER_NAME") or os.getenv("COMPUTERNAME") or "localhost" | ||
23 | PRINTER = os.getenv("PRINTER") or "printer" | ||
24 | |||
25 | local function connect(localhost, option) | ||
26 | local host = option.host or SERVER | ||
27 | local port = option.port or PORT | ||
28 | local skt | ||
29 | local try = socket.newtry(function() if skt then skt:close() end end) | ||
30 | if option.localbind then | ||
31 | -- bind to a local port (if we can) | ||
32 | local localport = 721 | ||
33 | local done, err | ||
34 | repeat | ||
35 | skt = socket.try(socket.tcp()) | ||
36 | try(skt:settimeout(30)) | ||
37 | done, err = skt:bind(localhost, localport) | ||
38 | if not done then | ||
39 | localport = localport + 1 | ||
40 | skt:close() | ||
41 | skt = nil | ||
42 | else break end | ||
43 | until localport > 731 | ||
44 | socket.try(skt, err) | ||
45 | else skt = socket.try(socket.tcp()) end | ||
46 | try(skt:connect(host, port)) | ||
47 | return { skt = skt, try = try } | ||
48 | end | ||
49 | |||
50 | --[[ | ||
51 | RFC 1179 | ||
52 | 5.3 03 - Send queue state (short) | ||
53 | |||
54 | +----+-------+----+------+----+ | ||
55 | | 03 | Queue | SP | List | LF | | ||
56 | +----+-------+----+------+----+ | ||
57 | Command code - 3 | ||
58 | Operand 1 - Printer queue name | ||
59 | Other operands - User names or job numbers | ||
60 | |||
61 | If the user names or job numbers or both are supplied then only those | ||
62 | jobs for those users or with those numbers will be sent. | ||
63 | |||
64 | The response is an ASCII stream which describes the printer queue. | ||
65 | The stream continues until the connection closes. Ends of lines are | ||
66 | indicated with ASCII LF control characters. The lines may also | ||
67 | contain ASCII HT control characters. | ||
68 | |||
69 | 5.4 04 - Send queue state (long) | ||
70 | |||
71 | +----+-------+----+------+----+ | ||
72 | | 04 | Queue | SP | List | LF | | ||
73 | +----+-------+----+------+----+ | ||
74 | Command code - 4 | ||
75 | Operand 1 - Printer queue name | ||
76 | Other operands - User names or job numbers | ||
77 | |||
78 | If the user names or job numbers or both are supplied then only those | ||
79 | jobs for those users or with those numbers will be sent. | ||
80 | |||
81 | The response is an ASCII stream which describes the printer queue. | ||
82 | The stream continues until the connection closes. Ends of lines are | ||
83 | indicated with ASCII LF control characters. The lines may also | ||
84 | contain ASCII HT control characters. | ||
85 | ]] | ||
86 | |||
87 | -- gets server acknowledement | ||
88 | local function recv_ack(con) | ||
89 | local ack = con.skt:receive(1) | ||
90 | con.try(string.char(0) == ack, "failed to receive server acknowledgement") | ||
91 | end | ||
92 | |||
93 | -- sends client acknowledement | ||
94 | local function send_ack(con) | ||
95 | local sent = con.skt:send(string.char(0)) | ||
96 | con.try(sent == 1, "failed to send acknowledgement") | ||
97 | end | ||
98 | |||
99 | -- sends queue request | ||
100 | -- 5.2 02 - Receive a printer job | ||
101 | -- | ||
102 | -- +----+-------+----+ | ||
103 | -- | 02 | Queue | LF | | ||
104 | -- +----+-------+----+ | ||
105 | -- Command code - 2 | ||
106 | -- Operand - Printer queue name | ||
107 | -- | ||
108 | -- Receiving a job is controlled by a second level of commands. The | ||
109 | -- daemon is given commands by sending them over the same connection. | ||
110 | -- The commands are described in the next section (6). | ||
111 | -- | ||
112 | -- After this command is sent, the client must read an acknowledgement | ||
113 | -- octet from the daemon. A positive acknowledgement is an octet of | ||
114 | -- zero bits. A negative acknowledgement is an octet of any other | ||
115 | -- pattern. | ||
116 | local function send_queue(con, queue) | ||
117 | queue = queue or PRINTER | ||
118 | local str = string.format("\2%s\10", queue) | ||
119 | local sent = con.skt:send(str) | ||
120 | con.try(sent == string.len(str), "failed to send print request") | ||
121 | recv_ack(con) | ||
122 | end | ||
123 | |||
124 | -- sends control file | ||
125 | -- 6.2 02 - Receive control file | ||
126 | -- | ||
127 | -- +----+-------+----+------+----+ | ||
128 | -- | 02 | Count | SP | Name | LF | | ||
129 | -- +----+-------+----+------+----+ | ||
130 | -- Command code - 2 | ||
131 | -- Operand 1 - Number of bytes in control file | ||
132 | -- Operand 2 - Name of control file | ||
133 | -- | ||
134 | -- The control file must be an ASCII stream with the ends of lines | ||
135 | -- indicated by ASCII LF. The total number of bytes in the stream is | ||
136 | -- sent as the first operand. The name of the control file is sent as | ||
137 | -- the second. It should start with ASCII "cfA", followed by a three | ||
138 | -- digit job number, followed by the host name which has constructed the | ||
139 | -- control file. Acknowledgement processing must occur as usual after | ||
140 | -- the command is sent. | ||
141 | -- | ||
142 | -- The next "Operand 1" octets over the same TCP connection are the | ||
143 | -- intended contents of the control file. Once all of the contents have | ||
144 | -- been delivered, an octet of zero bits is sent as an indication that | ||
145 | -- the file being sent is complete. A second level of acknowledgement | ||
146 | -- processing must occur at this point. | ||
147 | |||
148 | -- sends data file | ||
149 | -- 6.3 03 - Receive data file | ||
150 | -- | ||
151 | -- +----+-------+----+------+----+ | ||
152 | -- | 03 | Count | SP | Name | LF | | ||
153 | -- +----+-------+----+------+----+ | ||
154 | -- Command code - 3 | ||
155 | -- Operand 1 - Number of bytes in data file | ||
156 | -- Operand 2 - Name of data file | ||
157 | -- | ||
158 | -- The data file may contain any 8 bit values at all. The total number | ||
159 | -- of bytes in the stream may be sent as the first operand, otherwise | ||
160 | -- the field should be cleared to 0. The name of the data file should | ||
161 | -- start with ASCII "dfA". This should be followed by a three digit job | ||
162 | -- number. The job number should be followed by the host name which has | ||
163 | -- constructed the data file. Interpretation of the contents of the | ||
164 | -- data file is determined by the contents of the corresponding control | ||
165 | -- file. If a data file length has been specified, the next "Operand 1" | ||
166 | -- octets over the same TCP connection are the intended contents of the | ||
167 | -- data file. In this case, once all of the contents have been | ||
168 | -- delivered, an octet of zero bits is sent as an indication that the | ||
169 | -- file being sent is complete. A second level of acknowledgement | ||
170 | -- processing must occur at this point. | ||
171 | |||
172 | |||
173 | local function send_hdr(con, control) | ||
174 | local sent = con.skt:send(control) | ||
175 | con.try(sent and sent >= 1 , "failed to send header file") | ||
176 | recv_ack(con) | ||
177 | end | ||
178 | |||
179 | local function send_control(con, control) | ||
180 | local sent = con.skt:send(control) | ||
181 | con.try(sent and sent >= 1, "failed to send control file") | ||
182 | send_ack(con) | ||
183 | end | ||
184 | |||
185 | local function send_data(con,fh,size) | ||
186 | local buf | ||
187 | while size > 0 do | ||
188 | buf,message = fh:read(8192) | ||
189 | if buf then | ||
190 | st = con.try(con.skt:send(buf)) | ||
191 | size = size - st | ||
192 | else | ||
193 | con.try(size == 0, "file size mismatch") | ||
194 | end | ||
195 | end | ||
196 | recv_ack(con) -- note the double acknowledgement | ||
197 | send_ack(con) | ||
198 | recv_ack(con) | ||
199 | return size | ||
200 | end | ||
201 | |||
202 | |||
203 | --[[ | ||
204 | local control_dflt = { | ||
205 | "H"..string.sub(socket.hostname,1,31).."\10", -- host | ||
206 | "C"..string.sub(socket.hostname,1,31).."\10", -- class | ||
207 | "J"..string.sub(filename,1,99).."\10", -- jobname | ||
208 | "L"..string.sub(user,1,31).."\10", -- print banner page | ||
209 | "I"..tonumber(indent).."\10", -- indent column count ('f' only) | ||
210 | "M"..string.sub(mail,1,128).."\10", -- mail when printed user@host | ||
211 | "N"..string.sub(filename,1,131).."\10", -- name of source file | ||
212 | "P"..string.sub(user,1,31).."\10", -- user name | ||
213 | "T"..string.sub(title,1,79).."\10", -- title for banner ('p' only) | ||
214 | "W"..tonumber(width or 132).."\10", -- width of print f,l,p only | ||
215 | |||
216 | "f"..file.."\10", -- formatted print (remove control chars) | ||
217 | "l"..file.."\10", -- print | ||
218 | "o"..file.."\10", -- postscript | ||
219 | "p"..file.."\10", -- pr format - requires T, L | ||
220 | "r"..file.."\10", -- fortran format | ||
221 | "U"..file.."\10", -- Unlink (data file only) | ||
222 | } | ||
223 | ]] | ||
224 | |||
225 | -- generate a varying job number | ||
226 | local seq = 0 | ||
227 | local function newjob(connection) | ||
228 | seq = seq + 1 | ||
229 | return math.floor(socket.gettime() * 1000 + seq)%1000 | ||
230 | end | ||
231 | |||
232 | |||
233 | local format_codes = { | ||
234 | binary = 'l', | ||
235 | text = 'f', | ||
236 | ps = 'o', | ||
237 | pr = 'p', | ||
238 | fortran = 'r', | ||
239 | l = 'l', | ||
240 | r = 'r', | ||
241 | o = 'o', | ||
242 | p = 'p', | ||
243 | f = 'f' | ||
244 | } | ||
245 | |||
246 | -- lp.send{option} | ||
247 | -- requires option.file | ||
248 | |||
249 | send = socket.protect(function(option) | ||
250 | socket.try(option and base.type(option) == "table", "invalid options") | ||
251 | local file = option.file | ||
252 | socket.try(file, "invalid file name") | ||
253 | local fh = socket.try(io.open(file,"rb")) | ||
254 | local datafile_size = fh:seek("end") -- get total size | ||
255 | fh:seek("set") -- go back to start of file | ||
256 | local localhost = socket.dns.gethostname() or os.getenv("COMPUTERNAME") | ||
257 | or "localhost" | ||
258 | local con = connect(localhost, option) | ||
259 | -- format the control file | ||
260 | local jobno = newjob() | ||
261 | local localip = socket.dns.toip(localhost) | ||
262 | localhost = string.sub(localhost,1,31) | ||
263 | local user = string.sub(option.user or os.getenv("LPRUSER") or | ||
264 | os.getenv("USERNAME") or os.getenv("USER") or "anonymous", 1,31) | ||
265 | local lpfile = string.format("dfA%3.3d%-s", jobno, localhost); | ||
266 | local fmt = format_codes[option.format] or 'l' | ||
267 | local class = string.sub(option.class or localip or localhost,1,31) | ||
268 | local _,_,ctlfn = string.find(file,".*[%/%\\](.*)") | ||
269 | ctlfn = string.sub(ctlfn or file,1,131) | ||
270 | local cfile = | ||
271 | string.format("H%-s\nC%-s\nJ%-s\nP%-s\n%.1s%-s\nU%-s\nN%-s\n", | ||
272 | localhost, | ||
273 | class, | ||
274 | option.job or "LuaSocket", | ||
275 | user, | ||
276 | fmt, lpfile, | ||
277 | lpfile, | ||
278 | ctlfn); -- mandatory part of ctl file | ||
279 | if (option.banner) then cfile = cfile .. 'L'..user..'\10' end | ||
280 | if (option.indent) then cfile = cfile .. 'I'..base.tonumber(option.indent)..'\10' end | ||
281 | if (option.mail) then cfile = cfile .. 'M'..string.sub((option.mail),1,128)..'\10' end | ||
282 | if (fmt == 'p' and option.title) then cfile = cfile .. 'T'..string.sub((option.title),1,79)..'\10' end | ||
283 | if ((fmt == 'p' or fmt == 'l' or fmt == 'f') and option.width) then | ||
284 | cfile = cfile .. 'W'..base.tonumber(option,width)..'\10' | ||
285 | end | ||
286 | |||
287 | con.skt:settimeout(option.timeout or 65) | ||
288 | -- send the queue header | ||
289 | send_queue(con, option.queue) | ||
290 | -- send the control file header | ||
291 | local cfilecmd = string.format("\2%d cfA%3.3d%-s\n",string.len(cfile), jobno, localhost); | ||
292 | send_hdr(con,cfilecmd) | ||
293 | |||
294 | -- send the control file | ||
295 | send_control(con,cfile) | ||
296 | |||
297 | -- send the data file header | ||
298 | local dfilecmd = string.format("\3%d dfA%3.3d%-s\n",datafile_size, jobno, localhost); | ||
299 | send_hdr(con,dfilecmd) | ||
300 | |||
301 | -- send the data file | ||
302 | send_data(con,fh,datafile_size) | ||
303 | fh:close() | ||
304 | con.skt:close(); | ||
305 | return jobno, datafile_size | ||
306 | end) | ||
307 | |||
308 | -- | ||
309 | -- lp.query({host=,queue=printer|'*', format='l'|'s', list=}) | ||
310 | -- | ||
311 | query = socket.protect(function(p) | ||
312 | p = p or {} | ||
313 | local localhost = socket.dns.gethostname() or os.getenv("COMPUTERNAME") | ||
314 | or "localhost" | ||
315 | local con = connect(localhost,p) | ||
316 | local fmt | ||
317 | if string.sub(p.format or 's',1,1) == 's' then fmt = 3 else fmt = 4 end | ||
318 | con.try(con.skt:send(string.format("%c%s %s\n", fmt, p.queue or "*", | ||
319 | p.list or ""))) | ||
320 | local data = con.try(con.skt:receive("*a")) | ||
321 | con.skt:close() | ||
322 | return data | ||
323 | end) | ||
diff --git a/etc/qp.lua b/etc/qp.lua deleted file mode 100644 index 523238b..0000000 --- a/etc/qp.lua +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- Little program to convert to and from Quoted-Printable | ||
3 | -- LuaSocket sample files | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | local ltn12 = require("ltn12") | ||
7 | local mime = require("mime") | ||
8 | local convert | ||
9 | arg = arg or {} | ||
10 | local mode = arg and arg[1] or "-et" | ||
11 | if mode == "-et" then | ||
12 | local normalize = mime.normalize() | ||
13 | local qp = mime.encode("quoted-printable") | ||
14 | local wrap = mime.wrap("quoted-printable") | ||
15 | convert = ltn12.filter.chain(normalize, qp, wrap) | ||
16 | elseif mode == "-eb" then | ||
17 | local qp = mime.encode("quoted-printable", "binary") | ||
18 | local wrap = mime.wrap("quoted-printable") | ||
19 | convert = ltn12.filter.chain(qp, wrap) | ||
20 | else convert = mime.decode("quoted-printable") end | ||
21 | local source = ltn12.source.chain(ltn12.source.file(io.stdin), convert) | ||
22 | local sink = ltn12.sink.file(io.stdout) | ||
23 | ltn12.pump.all(source, sink) | ||
diff --git a/etc/tftp.lua b/etc/tftp.lua deleted file mode 100644 index ed99cd1..0000000 --- a/etc/tftp.lua +++ /dev/null | |||
@@ -1,154 +0,0 @@ | |||
1 | ----------------------------------------------------------------------------- | ||
2 | -- TFTP support for the Lua language | ||
3 | -- LuaSocket toolkit. | ||
4 | -- Author: Diego Nehab | ||
5 | ----------------------------------------------------------------------------- | ||
6 | |||
7 | ----------------------------------------------------------------------------- | ||
8 | -- Load required files | ||
9 | ----------------------------------------------------------------------------- | ||
10 | local base = _G | ||
11 | local table = require("table") | ||
12 | local math = require("math") | ||
13 | local string = require("string") | ||
14 | local socket = require("socket") | ||
15 | local ltn12 = require("ltn12") | ||
16 | local url = require("socket.url") | ||
17 | module("socket.tftp") | ||
18 | |||
19 | ----------------------------------------------------------------------------- | ||
20 | -- Program constants | ||
21 | ----------------------------------------------------------------------------- | ||
22 | local char = string.char | ||
23 | local byte = string.byte | ||
24 | |||
25 | PORT = 69 | ||
26 | local OP_RRQ = 1 | ||
27 | local OP_WRQ = 2 | ||
28 | local OP_DATA = 3 | ||
29 | local OP_ACK = 4 | ||
30 | local OP_ERROR = 5 | ||
31 | local OP_INV = {"RRQ", "WRQ", "DATA", "ACK", "ERROR"} | ||
32 | |||
33 | ----------------------------------------------------------------------------- | ||
34 | -- Packet creation functions | ||
35 | ----------------------------------------------------------------------------- | ||
36 | local function RRQ(source, mode) | ||
37 | return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0) | ||
38 | end | ||
39 | |||
40 | local function WRQ(source, mode) | ||
41 | return char(0, OP_RRQ) .. source .. char(0) .. mode .. char(0) | ||
42 | end | ||
43 | |||
44 | local function ACK(block) | ||
45 | local low, high | ||
46 | low = math.mod(block, 256) | ||
47 | high = (block - low)/256 | ||
48 | return char(0, OP_ACK, high, low) | ||
49 | end | ||
50 | |||
51 | local function get_OP(dgram) | ||
52 | local op = byte(dgram, 1)*256 + byte(dgram, 2) | ||
53 | return op | ||
54 | end | ||
55 | |||
56 | ----------------------------------------------------------------------------- | ||
57 | -- Packet analysis functions | ||
58 | ----------------------------------------------------------------------------- | ||
59 | local function split_DATA(dgram) | ||
60 | local block = byte(dgram, 3)*256 + byte(dgram, 4) | ||
61 | local data = string.sub(dgram, 5) | ||
62 | return block, data | ||
63 | end | ||
64 | |||
65 | local function get_ERROR(dgram) | ||
66 | local code = byte(dgram, 3)*256 + byte(dgram, 4) | ||
67 | local msg | ||
68 | _,_, msg = string.find(dgram, "(.*)\000", 5) | ||
69 | return string.format("error code %d: %s", code, msg) | ||
70 | end | ||
71 | |||
72 | ----------------------------------------------------------------------------- | ||
73 | -- The real work | ||
74 | ----------------------------------------------------------------------------- | ||
75 | local function tget(gett) | ||
76 | local retries, dgram, sent, datahost, dataport, code | ||
77 | local last = 0 | ||
78 | socket.try(gett.host, "missing host") | ||
79 | local con = socket.try(socket.udp()) | ||
80 | local try = socket.newtry(function() con:close() end) | ||
81 | -- convert from name to ip if needed | ||
82 | gett.host = try(socket.dns.toip(gett.host)) | ||
83 | con:settimeout(1) | ||
84 | -- first packet gives data host/port to be used for data transfers | ||
85 | local path = string.gsub(gett.path or "", "^/", "") | ||
86 | path = url.unescape(path) | ||
87 | retries = 0 | ||
88 | repeat | ||
89 | sent = try(con:sendto(RRQ(path, "octet"), gett.host, gett.port)) | ||
90 | dgram, datahost, dataport = con:receivefrom() | ||
91 | retries = retries + 1 | ||
92 | until dgram or datahost ~= "timeout" or retries > 5 | ||
93 | try(dgram, datahost) | ||
94 | -- associate socket with data host/port | ||
95 | try(con:setpeername(datahost, dataport)) | ||
96 | -- default sink | ||
97 | local sink = gett.sink or ltn12.sink.null() | ||
98 | -- process all data packets | ||
99 | while 1 do | ||
100 | -- decode packet | ||
101 | code = get_OP(dgram) | ||
102 | try(code ~= OP_ERROR, get_ERROR(dgram)) | ||
103 | try(code == OP_DATA, "unhandled opcode " .. code) | ||
104 | -- get data packet parts | ||
105 | local block, data = split_DATA(dgram) | ||
106 | -- if not repeated, write | ||
107 | if block == last+1 then | ||
108 | try(sink(data)) | ||
109 | last = block | ||
110 | end | ||
111 | -- last packet brings less than 512 bytes of data | ||
112 | if string.len(data) < 512 then | ||
113 | try(con:send(ACK(block))) | ||
114 | try(con:close()) | ||
115 | try(sink(nil)) | ||
116 | return 1 | ||
117 | end | ||
118 | -- get the next packet | ||
119 | retries = 0 | ||
120 | repeat | ||
121 | sent = try(con:send(ACK(last))) | ||
122 | dgram, err = con:receive() | ||
123 | retries = retries + 1 | ||
124 | until dgram or err ~= "timeout" or retries > 5 | ||
125 | try(dgram, err) | ||
126 | end | ||
127 | end | ||
128 | |||
129 | local default = { | ||
130 | port = PORT, | ||
131 | path ="/", | ||
132 | scheme = "tftp" | ||
133 | } | ||
134 | |||
135 | local function parse(u) | ||
136 | local t = socket.try(url.parse(u, default)) | ||
137 | socket.try(t.scheme == "tftp", "invalid scheme '" .. t.scheme .. "'") | ||
138 | socket.try(t.host, "invalid host") | ||
139 | return t | ||
140 | end | ||
141 | |||
142 | local function sget(u) | ||
143 | local gett = parse(u) | ||
144 | local t = {} | ||
145 | gett.sink = ltn12.sink.table(t) | ||
146 | tget(gett) | ||
147 | return table.concat(t) | ||
148 | end | ||
149 | |||
150 | get = socket.protect(function(gett) | ||
151 | if base.type(gett) == "string" then return sget(gett) | ||
152 | else return tget(gett) end | ||
153 | end) | ||
154 | |||