Skip to content

Instantly share code, notes, and snippets.

@Laeeth
Created January 15, 2015 04:48
Show Gist options
  • Save Laeeth/a4060e62fab5e3a1ea0d to your computer and use it in GitHub Desktop.
Save Laeeth/a4060e62fab5e3a1ea0d to your computer and use it in GitHub Desktop.
Using linux sockets to talk to dovecot doveadm
module doveadm;
import std.stdio;
import std.socket;
import std.string;
import std.array;
import std.c.linux.socket;
import core.sys.posix.sys.un;
import std.conv;
enum doveadmSocketPath= "/var/run/dovecot/doveadm-server";
private string tabify(string s)
{
string s2="";
foreach(char c;s)
if (c=='\t')
s2~=r"\t";
else
s2~=c;
return s2;
}
private string[] detab(string s)
{
return s.split("\t");
}
class UnixAddress: Address
{
private:
sockaddr_un sun;
this()
{
}
public:
override @property sockaddr* name()
{
return cast(sockaddr*)&sun;
}
override @property const(sockaddr)* name() const
{
return cast(const(sockaddr)*)&sun;
}
override @property socklen_t nameLen() const
{
return cast(socklen_t) sun.sizeof;
}
this(in char[] path)
{
sun.sun_family = AF_UNIX;
sun.sun_path.ptr[0..path.length] = cast(byte[])path;
sun.sun_path.ptr[path.length] = 0;
}
@property string path() const
{
return to!string(sun.sun_path.ptr);
}
override string toString() const
{
return path;
}
}
struct DoveADMClient
{
Socket sock;
string path;
string openMessage = "VERSION\tdoveadm-server\t1\t0\n";
this(string path)
{
this.path=path;
this.sock=new Socket(AddressFamily.UNIX, SocketType.STREAM, cast(ProtocolType)AF_UNIX);
auto z=new doveadm.UnixAddress(path);
sock.connect(new doveadm.UnixAddress(cast(char[])path));
sock.setOption(SocketOptionLevel.SOCKET,SocketOption.RCVTIMEO,dur!"msecs"(800));
writefln("* is it alive: %s", sock.getErrorText());
sock.setOption(SocketOptionLevel.SOCKET,SocketOption.SNDTIMEO,dur!"msecs"(800));
writefln("* is it alive: %s", sock.getErrorText());
sock.send(cast(ubyte[])openMessage);
writefln("* is it alive: %s", sock.getErrorText());
writefln("* sent handshake - waiting for reply");
auto ret=listen();
writefln("* got reply: %s",ret);
if (ret.indexOf("+")==-1)
throw new Exception("doveadm did not return the handshake");
writef(ret);
}
~this()
{
sock.shutdown(SocketShutdown.BOTH);
sock.close();
}
string[] sendCommand(string s)
{
if (sock is null)
throw new Exception("socket must be open");
if (sock.send(s~"\n")==0)
{
writefln("* couldnt send any bytes");
return null;
}
return(detab(listen()));
}
string listen()
{
string s;
ubyte[1024*1024] buf;
while(true)
{
auto result=sock.receive(buf); // flags
writefln("* result: %s",result);
if (result<=0)
return s;
s~=removechars(cast(string)(buf[0..result]),"\n");
}
assert(0);
}
string[] getUserGuid(string u)
{
return sendCommand("\t"~u~"\t"~"mailbox status\tguid\t*");
}
stringp[]
}
void main(string[] args)
{
auto doveadm=DoveADMClient(doveadmSocketPath);
writeln(doveadm.sendCommand("\tlaeeth@laeeth.com\tmailbox list"));
writeln(doveadm.getUserGuid("laeeth@laeeth.com"));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment