/usr/bin/smd-server is in syncmaildir 1.2.2-1ubuntu1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | #! /usr/bin/env lua5.1
--
-- Released under the terms of GPLv3 or at your option any later version.
-- No warranties.
-- Copyright Enrico Tassi <gares@fettunta.org>
require 'syncmaildir'
-- export to the global namespace all symbols
for k,v in pairs(syncmaildir) do _G[k] = v end
-- ============================= MAIN =====================================
function main()
-- sanity checks
assert_exists(MDDIFF)
assert_exists(XDELTA)
-- argument parsing
local exclude = {}
local usage = "Usage: "..arg[0]:match('[^/]+$')..
" [-vd] endpointname mailboxes...\n"
while #arg > 2 do
if arg[1] == '-v' or arg[1] == '--verbose' then
set_verbose(true)
table.remove(arg,1)
elseif arg[1] == '-d' or arg[1] == '--dry-run' then
set_dry_run(true)
table.remove(arg,1)
elseif arg[1] == '--exclude' then
exclude[#exclude + 1] = arg[1]
exclude[#exclude + 1] = arg[2]
table.remove(arg,1)
table.remove(arg,1)
else
break
end
end
if #arg < 2 then
io.stderr:write(usage)
os.exit(2)
end
local endpoint = arg[1]
table.remove(arg,1)
local dbfile = dbfile_name(endpoint, arg)
local xdelta = dbfile .. '.xdelta'
local dbfilemt = dbfile .. '.mtime'
local newdb = dbfile .. '.new'
local newdbmt = dbfilemt .. '.new'
local database_opt = '--db-file '.. dbfile
local mailbox_opt = table.concat(arg,' ')
local dry_opt = ''
if dry_run() then dry_opt = '-d' end
local exclude_opt = table.concat(exclude, ' ')
-- we check the protocol version and dbfile fingerprint
handshake(dbfile)
-- run mddiff and send the output to the client
local mddiff = MDDIFF..' '..dry_opt..' '..database_opt..' '..
exclude_opt..' '..mailbox_opt
local r = io.popen(mddiff,"r")
local sent = 0
while true do
local l = r:read("*l")
if l ~= nil then
sent = sent + 1
io.write(l,'\n')
else
break
end
end
r:close()
-- end of the first phase, now the client should
-- apply the diff eventually asking for the transmission
-- of some data
io.write('END\n')
io.flush()
-- process client commands
while true do
local l = io.read('*l')
if l == nil then
-- end of input stream, client is dead
log_error('Communication with client died unexpectedly\n')
os.exit(3)
end
if l:match('^COMMIT$') then
-- the client applied the diff, the new mailbox
-- fingerprint should be used for the next sync
local rc
if not dry_run() then
rc = os.execute(
XDELTA..' delta '..dbfile..' '..newdb..' '..xdelta)
else
local f = io.open(xdelta,'w')
f:close()
rc = 0 -- there is no newdb if --dry-run is given
end
if rc ~= 0 and rc ~= 256 then
log_error('Failed running `xdelta delta` on db file: '..rc)
os.exit(4)
end
transmit(io.stdout, xdelta, "all")
os.remove(xdelta)
elseif l:match('^DONE$') then
if not dry_run() then os.rename(newdb, dbfile) end
if not dry_run() then os.rename(newdbmt, dbfilemt) end
os.exit(0)
elseif l:match('^ABORT$') then
-- the client failed in applying the diff
log_error('Client aborted, removing '..
newdb..' and '..newdbmt..'\n')
if not dry_run() then os.remove(newdb) end
if not dry_run() then os.remove(newdbmt) end
os.exit(5)
elseif l:match('^GET ') then
local path = parse(l, '^GET (%S.*)$')
transmit(io.stdout, path, "all")
elseif l:match('^GETHEADER ') then
local path = parse(l, '^GETHEADER (%S.*)$')
transmit(io.stdout, path, "header")
elseif l:match('^GETBODY ') then
local path = parse(l, '^GETBODY (%S.*)$')
transmit(io.stdout, path, "body")
else
-- protocol error
log_error('Invalid command '..l..'\n')
os.exit(6)
end
end
end
-- no more globals
set_strict()
-- parachute for error
parachute(main, 7)
-- vim:set ts=4:
|