commit 81d064290c5a4f18ce59e165ed81b82d320ac61e
parent 4a2d861498b554c60ee70a4ede1cf4750bcfaacd
Author: pancake@localhost.localdomain <unknown>
Date: Mon, 12 Oct 2009 18:37:14 +0200
* Move makefile to the root of the project
* Added a decent README and the wip mails in doc/
Diffstat:
Makefile | | | 32 | ++++++++++++++++++++++++++++++++ |
README | | | 107 | +++++++++++++++++++++++++++++++++++-------------------------------------------- |
TODO | | | 1 | - |
dmc | | | 97 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
dmc.1 | | | 1 | + |
doc/random | | | 51 | +++++++++++++++++++++++++++++++++++++++++++++++++++ |
doc/wipmail.txt | | | 110 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
doc/wipmail2.txt | | | 70 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
imap4.c | | | 107 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
pop3.c | | | 139 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
smtp.c | | | 3 | +++ |
src/Makefile | | | 32 | -------------------------------- |
src/dmc | | | 97 | ------------------------------------------------------------------------------- |
src/imap4.c | | | 107 | ------------------------------------------------------------------------------- |
src/pop3.c | | | 139 | ------------------------------------------------------------------------------- |
src/smtp.c | | | 3 | --- |
16 files changed, 657 insertions(+), 439 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,32 @@
+CC?=gcc
+PREFIX?=/usr
+CFLAGS?=-Wall
+
+all: dmc-smtp dmc-pop3 dmc-imap4
+
+dmc-smtp: smtp.o
+ ${CC} ${LDFLAGS} smtp.o -o dmc-smtp
+
+dmc-pop3: pop3.o
+ ${CC} ${LDFLAGS} pop3.o -o dmc-pop3
+
+dmc-imap4: imap4.o
+ ${CC} ${LDFLAGS} imap4.o -o dmc-imap4
+
+install:
+ cp -f dmc ${PREFIX}/bin
+ cp -f dmc-smtp ${PREFIX}/bin
+ cp -f dmc-pop3 ${PREFIX}/bin
+ cp -f dmc-imap4 ${PREFIX}/bin
+
+uninstall:
+ rm -f ${PREFIX}/bin/dmc
+ rm -f ${PREFIX}/bin/dmc-smtp
+ rm -f ${PREFIX}/bin/dmc-pop3
+ rm -f ${PREFIX}/bin/dmc-imap4
+
+clean:
+ rm -f dmc-pop3 dmc-imap4 dmc-smtp *.o
+
+loc:
+ sloccount .
diff --git a/README b/README
@@ -1,61 +1,48 @@
- +-----+---------------------+
- | DMC | Dynamic Mail Client |
- +-----+---------------------+
-
-Sending mails:
---------------
- dmc-smtp ~/mail/outbox/001.eml
- [ $? = 0 ] && mv ~/mail/outbox/001.* ~/mail/sent/
-
-
-IMAP handling:
---------------
- Usage: dmc-imap [options] [host] [port] < commands > output
- dmc-imap -a plain -d ~/mail [host] [port]
-
- options:
- -a : auth method
- -d : base user mail directory
-
- commands:
- cd [folder]
- # SELECT "folder"
- 1003 [20:47:15] IMAP4> 51 SELECT "Sent Messages"
- 1004 [20:47:15] IMAP4< * FLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded)
- 1005 [20:47:15] IMAP4< * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded \*)] Flags permitted.
- 1006 [20:47:15] IMAP4< * 340 EXISTS
- 1007 [20:47:15] IMAP4< * 2 RECENT
- 1008 [20:47:15] IMAP4< * OK [UIDVALIDITY 1230118148] UIDs valid
- 1009 [20:47:15] IMAP4< * OK [UIDNEXT 341] Predicted next UID
- 1010 [20:47:15] IMAP4< 51 OK [READ-WRITE] Select completed.
-
- st : show status
- 2508 [20:48:11] IMAP4> 60 STATUS "Spam.learn-ham" (MESSAGES UIDNEXT UIDVALIDITY UNSEEN)
- 2509 [20:48:12] IMAP4< * STATUS "Spam.learn-ham" (MESSAGES 0 UIDNEXT 1 UIDVALIDITY 1211795420 UNSEEN 0)
- 2510 [20:48:12] IMAP4< 60 OK Status completed.
-
- ls [num] : list num mails (can be used to check for new mail)
- cp = copy a mail from one folder to other
- mv = copy+remove
- rm = remove mail
- lt = list folder tree
-
-LOGIN
- Example: C: a001 LOGIN SMITH SESAME
- S: a001 OK LOGIN completed
-SELECT
- Example: C: A142 SELECT INBOX
- S: * 172 EXISTS
- S: * 1 RECENT
- S: * OK [UNSEEN 12] Message 12 is first unseen
- S: * OK [UIDVALIDITY 3857529045] UIDs valid
- S: * OK [UIDNEXT 4392] Predicted next UID
- S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
- S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
- S: A142 OK [READ-WRITE] SELECT completed
-CREATE
- Example: C: A003 CREATE owatagusiam/
- S: A003 OK CREATE completed
- C: A004 CREATE owatagusiam/blurdybloop
- S: A004 OK CREATE completed
+dmc - dynamic mail client
+=========================
+dmc is a minimalist email client solution
+
+Requirements
+------------
+ netcat (nc) for plain TCP connections
+ openssl binary for SSL encrypted
+ msmtp if you want to use
+
+
+Installation
+------------
+Few binaries will be copied into the bin directory
+
+ make all install PREFIX=/usr
+
+
+Configuration
+-------------
+Accounting information is stored in ~/.dmc/acc and can be
+edited with
+
+ dmc -e myaccount
+
+Running
+-------
+Start it in daemon mode
+
+ dmc -d
+
+To send a mail add the contact to your addressbook
+
+ echo 'user <foo@bar.com>' > ~/.dmc/addrbook
+
+ or edit the addressbook
+
+ dmc -a
+
+Then type the mail:
+
+ XXX: This is not correct
+
+Add attachments:
+
+ $EDITOR msg
+ dmc-mime msg attach1.zip | dmc -m `dmc -a user`
diff --git a/TODO b/TODO
@@ -1 +0,0 @@
-* --stop and pid registration is broken
diff --git a/dmc b/dmc
@@ -0,0 +1,97 @@
+#!/bin/sh
+#
+# Dynamic Mail Client
+#
+
+VERSION="0.1"
+COPYRIGHT="Copyleft -- pancake@nopcode.org"
+
+[ -n "${EDITOR}" ] && EDITOR=vim
+mkdir -p ~/.dmc/mail
+mkdir -p ~/.dmc/tmp
+mkdir -p ~/.dmc/acc
+
+function acc_daemon {
+ FIFO=~/.dmc/tmp/${NAME}.fifo
+ INPUT=~/.dmc/tmp/${NAME}.input
+ OUTPUT=~/.dmc/tmp/${NAME}.output
+
+ if [ ${SSL} = 1 ]; then
+ NETCMD="openssl s_client -host $HOST -port $POST"
+ else
+ NETCMD="nc $HOST $PORT"
+ fi
+
+ echo "Starting $NAME account daemon..."
+
+ rm -f ${INPUT}
+ mkfifo ${INPUT}
+# echo login ${USER} ${PASS} > ${INPUT}
+ (while : ; do cat ${INPUT} ; done) | \
+ ./dmc-${PROTOCOL} $FIFO 2> ${OUTPUT} | $NETCMD > $FIFO
+ rm -f ${INPUT}
+}
+
+function start_account_daemons {
+ i=0
+ for a in ~/.dmc/acc/* ; do
+ ( source $a ; acc_daemon ) &
+ i=$(($i+1))
+ done
+ if [ "$i" = 0 ]; then
+ echo "No accounts defined in ~/.dmc/acc"
+ exit 1
+ fi
+}
+
+function print_account_template {
+ echo "NAME='test'"
+ echo "SSL=0"
+ echo "PROTOCOL='pop3,imap4'"
+ echo "HOST=serverhost.com"
+ echo "PORT=110"
+ echo "USER='username'"
+ echo "PASS='password'"
+}
+
+case "$1" in
+"-d"|"--start")
+ start_account_daemons
+ ;;
+"-k"|"--stop")
+ for a in ~/.dmc/tmp/*.input ; do
+ echo $a
+ echo exit > $a
+ rm -f ~/.dmc/tmp/$a
+ done
+ ;;
+"-e"|"--edit")
+ if [ -n "$2" ]; then
+ if [ -n "`cat ~/.dmc/acc/$2`" ]; then
+ print_account_template "$2" > ~/.dmc/acc/$2
+ fi
+ vim ~/.dmc/acc/$2
+ # Remove account if empty
+ if [ -z "`cat ~/.dmc/acc/$2`" ]; then
+ rm ~/.dmc/acc/$2
+ fi
+ else
+ echo "Usage: dmc -e [accountname]"
+ fi
+ ;;
+"-a"|"--addr")
+ if [ -n "$2" ]; then
+ grep -e "$2" ~/.dmc/addrbook
+ else
+ ${EDITOR} ~/.dmc/addrbook
+ fi
+ ;;
+"-v"|"--version")
+ echo "dmc v${VERSION} ${COPYRIGHT}"
+ ;;
+"--help"|"-h"|*)
+ echo "Usage: dmc [-e acc] [-a addr] [-hvdk]"
+ ;;
+esac
+
+exit 0
diff --git a/dmc.1 b/dmc.1
@@ -0,0 +1 @@
+TODO
diff --git a/doc/random b/doc/random
@@ -0,0 +1,51 @@
+IMAP handling:
+--------------
+ Usage: dmc-imap [options] [host] [port] < commands > output
+ dmc-imap -a plain -d ~/mail [host] [port]
+
+ options:
+ -a : auth method
+ -d : base user mail directory
+
+ commands:
+ cd [folder]
+ # SELECT "folder"
+ 1003 [20:47:15] IMAP4> 51 SELECT "Sent Messages"
+ 1004 [20:47:15] IMAP4< * FLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded)
+ 1005 [20:47:15] IMAP4< * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded \*)] Flags permitted.
+ 1006 [20:47:15] IMAP4< * 340 EXISTS
+ 1007 [20:47:15] IMAP4< * 2 RECENT
+ 1008 [20:47:15] IMAP4< * OK [UIDVALIDITY 1230118148] UIDs valid
+ 1009 [20:47:15] IMAP4< * OK [UIDNEXT 341] Predicted next UID
+ 1010 [20:47:15] IMAP4< 51 OK [READ-WRITE] Select completed.
+
+ st : show status
+ 2508 [20:48:11] IMAP4> 60 STATUS "Spam.learn-ham" (MESSAGES UIDNEXT UIDVALIDITY UNSEEN)
+ 2509 [20:48:12] IMAP4< * STATUS "Spam.learn-ham" (MESSAGES 0 UIDNEXT 1 UIDVALIDITY 1211795420 UNSEEN 0)
+ 2510 [20:48:12] IMAP4< 60 OK Status completed.
+
+ ls [num] : list num mails (can be used to check for new mail)
+ cp = copy a mail from one folder to other
+ mv = copy+remove
+ rm = remove mail
+ lt = list folder tree
+
+LOGIN
+ Example: C: a001 LOGIN SMITH SESAME
+ S: a001 OK LOGIN completed
+SELECT
+ Example: C: A142 SELECT INBOX
+ S: * 172 EXISTS
+ S: * 1 RECENT
+ S: * OK [UNSEEN 12] Message 12 is first unseen
+ S: * OK [UIDVALIDITY 3857529045] UIDs valid
+ S: * OK [UIDNEXT 4392] Predicted next UID
+ S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
+ S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
+ S: A142 OK [READ-WRITE] SELECT completed
+CREATE
+ Example: C: A003 CREATE owatagusiam/
+ S: A003 OK CREATE completed
+ C: A004 CREATE owatagusiam/blurdybloop
+ S: A004 OK CREATE completed
+
diff --git a/doc/wipmail.txt b/doc/wipmail.txt
@@ -0,0 +1,110 @@
+markus schnalke wrote:
+> [2009-10-06 16:26] pancake <pancake@youterm.com>
+>
+>> PD: Actually I have not found a more fast, usable and simplest mail client
+>> than the one shipped with iphone-os. And no, fetchmail,mutt,claws,telnet
+>> are not decent solutions. Should we open another thread to create a suckless
+>> mail client?
+>>
+>
+> What do you mean with ``mail client''? MTA, MUA, MDA, or all of them in one?
+>
+A solution that manages MTA, MUA, MDA and MDMA plus LSD in a simple
+way.
+
+This is:
+ - Keep a partial local cache of the mails (only last 50?)
+ - imap support server search, so why i have to mirror the folders
+with 53200 mails?
+ - Only sync selected folders automatically or every N minutes
+ - Attachments should be only retrieved in a second stage (on slow
+connections
+ is really useful)
+
+Client must provide a simple tree way to walk on folders (filesystem?)
+every time a mail is fetched a file is created and it is touched with
+the specified timestamp.
+
+I already wrote a patch for msmtp that checks for the MX entry for a
+domain to
+automatically specify the remote SMTP server, so no need to configure
+any smtp
+server for sending mails. I find this solution much simpler for most
+situations (unless
+you are on a restricted network that only allows you to connect to your
+local smtp)
+
+So, what I see here is a simple application that manages files in
+directories and allows to create formatted files (using a template) on
+some directories using $EDITOR,
+a command to check files in Outbox to push them to remote servers and commit
+them into the Sent directory.
+
+The basic imap operations can be easily mapped as filesystem ones:
+ - list, copy, move, remove
+
+Just having a simple application to manage pop3/smtp with those minimal
+operations
+and writing a simple frontend to edit files on certain directories based
+on templates.
+
+Stuff like gpg, html2text (or text2html for those who wants to raise
+hate on mailing
+lists), filters to format a mail into a 'reply' format prefixing lines
+with '>' ... are just
+pre and post-hooks when calling the $EDITOR or $PAGER.
+
+The only missing thing I see in this model is the part of attached
+files. This can be
+solved by having a directory with the same filename of the mail plus
+.files and have
+an application to serialize mail+attachments into a single text stream
+before sending
+it to the smtp (maybe using msmtp) can be ideal.
+
+To setup accounts I can think on a single entrypoint with simple format
+that configures
+the rest of applications to work with.
+
+Multiple accounts should be managed by this approach. Marking emails as
+read/...
+can be just a sed script changing a header.
+
+I have never understood why there is no decent mail implementation like
+the one
+explained above. The only problematic to implement such thing is the
+lack of decent
+smtp/pop/imap clients. I think that ssl support can be done by local
+openssl bouncers.
+
+Another *important* thing is that the SSL stuff must be checked, so in
+this way you
+can setup any kind of secure connection without having to reconfigure
+your mail
+client. This is: connecting to localhost:110 to bounce the socket to an
+VPN or an DNSTX
+network (or TOR, etc...), the client will just know nothing about the
+underlying network,
+and the bouncer app will be the one to ensure that the connection is not
+broken.
+
+Network *must* be an async dependency for a mail client, so I hate when
+the client gets
+locked because of a network cut or slowdown, it is just something that
+cannot be understood
+nowadays.
+
+By having all this simple setup done (in a single package, please, i
+dont want to configure
+3 or 4 programs to get my email working) i can imagine a lot of
+automatizations in scripts
+to autoreply emails, filter spam, etc.. And the GUI is actually a
+filesystem.
+
+Email syncing is not only a thing of pop3/imap, we can also think on
+using ssh or fuse to
+access/sync to our remote mailboxes or maildirs.
+
+--pancake
+
+
diff --git a/doc/wipmail2.txt b/doc/wipmail2.txt
@@ -0,0 +1,70 @@
+
+I've managed to build tinymail..but a gobject framework of 16MB size is
+not exactly
+minimal, tiny or suckless in any way.
+
+The repository comes with no commandline or non-gtk dependent example.
+
+I still think that it is possible to implement a smtp/pop3/imap protocol
+handler in less
+than 1000LOC, all protocols are text based and by just defining a few
+functions for
+handling timeouts, responses and so on shouldnt be that hard.
+
+6 years ago I wrote a mail daemon (SMTP) in about 500LOC able to manage
+mbox,
+several auth methods and mutliple connections at the same time.
+
+fetchmail has lot of unnecessary features and lacks many useful
+functionalities.
+
+msmtp is cool, but I always find it unnecesarily complex for the things
+it has to do. For
+example, the network layer if wrapped by a bouncer can permit to keep
+connections
+alive, add encription, tunels and many other funny stuff.
+
+What I'm proposing is a simple setup with wrappers for
+sendmail,msmtp,whatever that
+can be exchanged by just changing a hook script.
+
+About attaching files I have some minimal base64 algorithms, so it
+should be that hard
+to make it work in stream like:
+
+ $ cat mail | add-attachments mail.d/* | msmtp mail@to.com
+
+And the same for extracting the attachments.
+
+I dont really think this is a loss of time (yeah, you can hate me), but
+I hate to be forced
+to use bloatware everywhere.
+
+I also use tinymail on the n810 because is the one that comes by default
+in the last
+firmwares because is just much better than the monolitic approach from
+Nokia, but
+having 16MB++ of memory slurped by a mail library on an embedded device
+is imho
+not a good thing. But I understand that having dbus to avoid doing
+innecessary stuff
+when the device is offline and earn battery is a good thing, but at
+least I would prefer
+to have my own minimal stack of mail management.
+
+
+--pancake
+
+Kurt H Maier wrote:
+> Check out tinymail[1]. This guy took a pretty cerebral approach to
+> developing his MUA back-end library. I've used it in the form of
+> Modest[2] on my Nokia n810.
+>
+> Personally, I'd hate to see any more dev hours wasted on garbage like
+> imap or pop3. ssh/rsyncing maildir to form a 'local copy,' then
+> 'commiting' changes back seems much saner to me.
+>
+> [1] - http://tinymail.org/
+> [2] - http://modest.garage.maemo.org/
+>
+>
diff --git a/imap4.c b/imap4.c
@@ -0,0 +1,107 @@
+/* dmc :: Copyleft -- pancake (at) nopcode (dot) org */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static char word[1024];
+static int ctr = 1;
+
+static char *getword() {
+ fscanf(stdin, "%127s", word);
+ if (feof(stdin))
+ *word = '\0';
+ return word;
+}
+
+static int waitreply() {
+ char *str;
+ int ret = -1;
+ fgets(word, sizeof(word), stdin);
+ if (atoi(word) != ctr-1)
+ fprintf(stderr, "Invalid sequence number received\n");
+ if ( (str = strchr(word, ' ')) ) {
+ if (!memcmp(str+1, "OK", 3))
+ ret = 1;
+ else if (!memcmp(str+1, "NO", 4))
+ ret = 0;
+ }
+ return ret; // 1 if true, 0 if false
+}
+
+#if 0
+LIST - list all folders
+LSUB - list all subscribed folders
+SUBSCRIBE - subcribe a folder
+CHECK - ???
+CLOSE - commit the delete stuff (maybe must be done after rm)
+EXPUNGE - permanent remove of deltec
+SEARCH - ...
+RECENT - show the number of recent messages
+#endif
+static int doword(char *word) {
+ int ret = 1;
+ if (*word == '\0' || !strcmp(word, "exit")) {
+ printf("%d LOGOUT\n", ctr++);
+ waitreply();
+ ret = 0;
+ } else
+ if (!strcmp(word, "help") || !strcmp(word, "?")) {
+ fprintf(stderr, "Use: ls lsdir cat head rm rmdir login exit mvdir\n");
+ } else
+ if (!strcmp(word, "ls")) {
+// TODO:
+ printf("LIST\n");
+ waitreply();
+ } else
+ if (!strcmp(word, "cd")) {
+ printf("%d SELECT %s\n", ctr++, getword());
+ waitreply();
+ } else
+ if (!strcmp(word, "search")) {
+ printf("%d SEARCH TEXT \"%s\"\n", ctr++, getword());
+ waitreply();
+ } else
+ if (!strcmp(word, "lsdir")) {
+ printf("%d LIST \"\" *\n", ctr++);
+ waitreply();
+ } else
+ if (!strcmp(word, "cat")) {
+ printf("%d FETCH %d ALL\n",
+ ctr++, atoi(getword()));
+ waitreply();
+ } else
+ if (!strcmp(word, "head")) {
+ printf("%d FETCH %d body[header]\n",
+ ctr++, atoi(getword()));
+ waitreply();
+ } else
+ if (!strcmp(word, "mvdir")) {
+ printf("%d RENAME %s %s\n",
+ ctr++, getword(), getword());
+ } else
+ if (!strcmp(word, "rm")) {
+// TODO:
+ printf("DELE %d\n", atoi(getword()));
+ waitreply();
+ } else
+ if (!strcmp(word, "rmdir")) {
+ printf("%d DELETE %d\n",
+ ctr++, atoi(getword()));
+ waitreply();
+ } else
+ if (!strcmp(word, "login")) {
+ printf("%d LOGIN %s %s\n",
+ ctr++, getword(), getword());
+ waitreply();
+ } else {
+ printf("%d NOOP\n", ctr++);
+ waitreply();
+ }
+ return ret;
+}
+
+int main() {
+ while(doword(getword()));
+ return 0;
+}
diff --git a/pop3.c b/pop3.c
@@ -0,0 +1,139 @@
+/* dmc :: Copyleft -- pancake (at) nopcode (dot) org */
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+
+
+static char *cmd = NULL;
+static char word[1024];
+static char *fifo;
+static int ff;
+
+/* XXX : Use of stdin FILE* fails when using fifo files */
+static char *getword() {
+ fscanf(stdin, "%255s", word);
+ if (feof(stdin))
+ *word = '\0';
+ return word;
+}
+
+static int ready() {
+ struct pollfd fds[1];
+ fds[0].fd = ff;
+ fds[0].events = POLLIN|POLLPRI;
+ fds[0].revents = POLLNVAL|POLLHUP|POLLERR;
+ return poll((struct pollfd *)&fds, 1, 10);
+}
+
+static int waitreply(int lock) {
+ char *ch, *str = word;
+ int ret, reply = -1;
+ fflush(stdout);
+ while(lock || ready()) {
+ lock = 0;
+ ret = read(ff, word, 512);
+ if (ret<1)
+ break;
+ word[ret] = 0;
+ if (reply==-1) {
+ ch = strchr(str, '\r');
+ if (!ch) ch = strchr(str, '\n');
+ if (ch) {
+ if (!memcmp(word, "+OK", 3))
+ reply = 1;
+ else
+ if (!memcmp(word, "-ERR", 4))
+ reply = 0;
+ *ch = 0;
+ fprintf(stderr, "%s %d \"%s\"\n", cmd, ret, str);
+ str = ch+((ch[1]=='\n')?2:1);
+ }
+ }
+ // TODO: \r \n issues
+ ch = strstr(str, "\r\n.");
+ if (ch)
+ *ch = '\0';
+ fprintf(stderr, "%s\n", str);
+ }
+ fflush(stderr);
+ write(2, "\x00", 1); // end of output
+ return reply;
+}
+
+static int doword(char *word) {
+ int ret = 1;
+ free (cmd);
+ cmd = strdup(word);
+ //if (*word == '\0' || !strcmp(word, "exit")) {
+ if (*word == '\0') {
+ /* Do nothing */
+ } else
+ if (!strcmp(word, "exit")) {
+ printf("QUIT\n");
+ waitreply(1);
+ ret = 0;
+ } else
+ if (!strcmp(word, "help") || !strcmp(word, "?")) {
+ fprintf(stderr, "Use: ls cat head rm login exit\n");
+ } else
+ if (!strcmp(word, "ls")) {
+ printf("LIST\n");
+ waitreply(1);
+ } else
+ if (!strcmp(word, "cat")) {
+ printf("RETR %d\n", atoi(getword()));
+ waitreply(1);
+ } else
+ if (!strcmp(word, "head")) {
+ printf("TOP %d\n", atoi(getword()));
+ waitreply(1);
+ } else
+ if (!strcmp(word, "rm")) {
+ printf("DELE %d\n", atoi(getword()));
+ waitreply(1);
+ } else
+ if (!strcmp(word, "login")) {
+ printf("USER %s\n", getword());
+ waitreply(1);
+ printf("PASS %s\n", getword());
+ waitreply(1);
+ } else printf("NOOP\n");
+ return ret;
+}
+
+static void parseoutput(void) {
+ while(!feof(stdin)) {
+ sleep(1);
+ printf("TODO\n");
+ }
+}
+
+static void cleanup(int foo) {
+ close(ff);
+ unlink(fifo);
+ exit(0);
+}
+
+int main(int argc, char **argv) {
+ if (argc>1) {
+ signal(SIGINT, cleanup);
+ fifo = argv[1];
+ mkfifo(fifo, 0600);
+ ff = open(fifo, O_RDONLY);
+ if (ff == -1) {
+ fprintf(stderr, "Cannot open fifo file.\n");
+ return 1;
+ }
+ waitreply(1);
+ while(doword(getword()));
+ cleanup(0);
+ } else parseoutput();
+ return 0;
+}
diff --git a/smtp.c b/smtp.c
@@ -0,0 +1,3 @@
+int main() {
+ return 0;
+}
diff --git a/src/Makefile b/src/Makefile
@@ -1,32 +0,0 @@
-CC?=gcc
-PREFIX?=/usr
-CFLAGS?=-Wall
-
-all: dmc-smtp dmc-pop3 dmc-imap4
-
-dmc-smtp: smtp.o
- ${CC} ${LDFLAGS} smtp.o -o dmc-smtp
-
-dmc-pop3: pop3.o
- ${CC} ${LDFLAGS} pop3.o -o dmc-pop3
-
-dmc-imap4: imap4.o
- ${CC} ${LDFLAGS} imap4.o -o dmc-imap4
-
-install:
- cp -f dmc ${PREFIX}/bin
- cp -f dmc-smtp ${PREFIX}/bin
- cp -f dmc-pop3 ${PREFIX}/bin
- cp -f dmc-imap4 ${PREFIX}/bin
-
-uninstall:
- rm -f ${PREFIX}/bin/dmc
- rm -f ${PREFIX}/bin/dmc-smtp
- rm -f ${PREFIX}/bin/dmc-pop3
- rm -f ${PREFIX}/bin/dmc-imap4
-
-clean:
- rm -f dmc-pop3 dmc-imap4 dmc-smtp *.o
-
-loc:
- sloccount .
diff --git a/src/dmc b/src/dmc
@@ -1,97 +0,0 @@
-#!/bin/sh
-#
-# Dynamic Mail Client
-#
-
-VERSION="0.1"
-COPYRIGHT="Copyleft -- pancake@nopcode.org"
-
-[ -n "${EDITOR}" ] && EDITOR=vim
-mkdir -p ~/.dmc/mail
-mkdir -p ~/.dmc/tmp
-mkdir -p ~/.dmc/acc
-
-function acc_daemon {
- FIFO=~/.dmc/tmp/${NAME}.fifo
- INPUT=~/.dmc/tmp/${NAME}.input
- OUTPUT=~/.dmc/tmp/${NAME}.output
-
- if [ ${SSL} = 1 ]; then
- NETCMD="openssl s_client -host $HOST -port $POST"
- else
- NETCMD="nc $HOST $PORT"
- fi
-
- echo "Starting $NAME account daemon..."
-
- rm -f ${INPUT}
- mkfifo ${INPUT}
-# echo login ${USER} ${PASS} > ${INPUT}
- (while : ; do cat ${INPUT} ; done) | \
- ./dmc-${PROTOCOL} $FIFO 2> ${OUTPUT} | $NETCMD > $FIFO
- rm -f ${INPUT}
-}
-
-function start_account_daemons {
- i=0
- for a in ~/.dmc/acc/* ; do
- ( source $a ; acc_daemon ) &
- i=$(($i+1))
- done
- if [ "$i" = 0 ]; then
- echo "No accounts defined in ~/.dmc/acc"
- exit 1
- fi
-}
-
-function print_account_template {
- echo "NAME='test'"
- echo "SSL=0"
- echo "PROTOCOL='pop3,imap4'"
- echo "HOST=serverhost.com"
- echo "PORT=110"
- echo "USER='username'"
- echo "PASS='password'"
-}
-
-case "$1" in
-"-d"|"--start")
- start_account_daemons
- ;;
-"-k"|"--stop")
- for a in ~/.dmc/tmp/*.input ; do
- echo $a
- echo exit > $a
- rm -f ~/.dmc/tmp/$a
- done
- ;;
-"-e"|"--edit")
- if [ -n "$2" ]; then
- if [ -n "`cat ~/.dmc/acc/$2`" ]; then
- print_account_template "$2" > ~/.dmc/acc/$2
- fi
- vim ~/.dmc/acc/$2
- # Remove account if empty
- if [ -z "`cat ~/.dmc/acc/$2`" ]; then
- rm ~/.dmc/acc/$2
- fi
- else
- echo "Usage: dmc -e [accountname]"
- fi
- ;;
-"-a"|"--addr")
- if [ -n "$2" ]; then
- grep -e "$2" ~/.dmc/addrbook
- else
- ${EDITOR} ~/.dmc/addrbook
- fi
- ;;
-"-v"|"--version")
- echo "dmc v${VERSION} ${COPYRIGHT}"
- ;;
-"--help"|"-h"|*)
- echo "Usage: dmc [-e acc] [-a addr] [-hvdk]"
- ;;
-esac
-
-exit 0
diff --git a/src/imap4.c b/src/imap4.c
@@ -1,107 +0,0 @@
-/* dmc :: Copyleft -- pancake (at) nopcode (dot) org */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-static char word[1024];
-static int ctr = 1;
-
-static char *getword() {
- fscanf(stdin, "%127s", word);
- if (feof(stdin))
- *word = '\0';
- return word;
-}
-
-static int waitreply() {
- char *str;
- int ret = -1;
- fgets(word, sizeof(word), stdin);
- if (atoi(word) != ctr-1)
- fprintf(stderr, "Invalid sequence number received\n");
- if ( (str = strchr(word, ' ')) ) {
- if (!memcmp(str+1, "OK", 3))
- ret = 1;
- else if (!memcmp(str+1, "NO", 4))
- ret = 0;
- }
- return ret; // 1 if true, 0 if false
-}
-
-#if 0
-LIST - list all folders
-LSUB - list all subscribed folders
-SUBSCRIBE - subcribe a folder
-CHECK - ???
-CLOSE - commit the delete stuff (maybe must be done after rm)
-EXPUNGE - permanent remove of deltec
-SEARCH - ...
-RECENT - show the number of recent messages
-#endif
-static int doword(char *word) {
- int ret = 1;
- if (*word == '\0' || !strcmp(word, "exit")) {
- printf("%d LOGOUT\n", ctr++);
- waitreply();
- ret = 0;
- } else
- if (!strcmp(word, "help") || !strcmp(word, "?")) {
- fprintf(stderr, "Use: ls lsdir cat head rm rmdir login exit mvdir\n");
- } else
- if (!strcmp(word, "ls")) {
-// TODO:
- printf("LIST\n");
- waitreply();
- } else
- if (!strcmp(word, "cd")) {
- printf("%d SELECT %s\n", ctr++, getword());
- waitreply();
- } else
- if (!strcmp(word, "search")) {
- printf("%d SEARCH TEXT \"%s\"\n", ctr++, getword());
- waitreply();
- } else
- if (!strcmp(word, "lsdir")) {
- printf("%d LIST \"\" *\n", ctr++);
- waitreply();
- } else
- if (!strcmp(word, "cat")) {
- printf("%d FETCH %d ALL\n",
- ctr++, atoi(getword()));
- waitreply();
- } else
- if (!strcmp(word, "head")) {
- printf("%d FETCH %d body[header]\n",
- ctr++, atoi(getword()));
- waitreply();
- } else
- if (!strcmp(word, "mvdir")) {
- printf("%d RENAME %s %s\n",
- ctr++, getword(), getword());
- } else
- if (!strcmp(word, "rm")) {
-// TODO:
- printf("DELE %d\n", atoi(getword()));
- waitreply();
- } else
- if (!strcmp(word, "rmdir")) {
- printf("%d DELETE %d\n",
- ctr++, atoi(getword()));
- waitreply();
- } else
- if (!strcmp(word, "login")) {
- printf("%d LOGIN %s %s\n",
- ctr++, getword(), getword());
- waitreply();
- } else {
- printf("%d NOOP\n", ctr++);
- waitreply();
- }
- return ret;
-}
-
-int main() {
- while(doword(getword()));
- return 0;
-}
diff --git a/src/pop3.c b/src/pop3.c
@@ -1,139 +0,0 @@
-/* dmc :: Copyleft -- pancake (at) nopcode (dot) org */
-
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <poll.h>
-
-
-static char *cmd = NULL;
-static char word[1024];
-static char *fifo;
-static int ff;
-
-/* XXX : Use of stdin FILE* fails when using fifo files */
-static char *getword() {
- fscanf(stdin, "%255s", word);
- if (feof(stdin))
- *word = '\0';
- return word;
-}
-
-static int ready() {
- struct pollfd fds[1];
- fds[0].fd = ff;
- fds[0].events = POLLIN|POLLPRI;
- fds[0].revents = POLLNVAL|POLLHUP|POLLERR;
- return poll((struct pollfd *)&fds, 1, 10);
-}
-
-static int waitreply(int lock) {
- char *ch, *str = word;
- int ret, reply = -1;
- fflush(stdout);
- while(lock || ready()) {
- lock = 0;
- ret = read(ff, word, 512);
- if (ret<1)
- break;
- word[ret] = 0;
- if (reply==-1) {
- ch = strchr(str, '\r');
- if (!ch) ch = strchr(str, '\n');
- if (ch) {
- if (!memcmp(word, "+OK", 3))
- reply = 1;
- else
- if (!memcmp(word, "-ERR", 4))
- reply = 0;
- *ch = 0;
- fprintf(stderr, "%s %d \"%s\"\n", cmd, ret, str);
- str = ch+((ch[1]=='\n')?2:1);
- }
- }
- // TODO: \r \n issues
- ch = strstr(str, "\r\n.");
- if (ch)
- *ch = '\0';
- fprintf(stderr, "%s\n", str);
- }
- fflush(stderr);
- write(2, "\x00", 1); // end of output
- return reply;
-}
-
-static int doword(char *word) {
- int ret = 1;
- free (cmd);
- cmd = strdup(word);
- //if (*word == '\0' || !strcmp(word, "exit")) {
- if (*word == '\0') {
- /* Do nothing */
- } else
- if (!strcmp(word, "exit")) {
- printf("QUIT\n");
- waitreply(1);
- ret = 0;
- } else
- if (!strcmp(word, "help") || !strcmp(word, "?")) {
- fprintf(stderr, "Use: ls cat head rm login exit\n");
- } else
- if (!strcmp(word, "ls")) {
- printf("LIST\n");
- waitreply(1);
- } else
- if (!strcmp(word, "cat")) {
- printf("RETR %d\n", atoi(getword()));
- waitreply(1);
- } else
- if (!strcmp(word, "head")) {
- printf("TOP %d\n", atoi(getword()));
- waitreply(1);
- } else
- if (!strcmp(word, "rm")) {
- printf("DELE %d\n", atoi(getword()));
- waitreply(1);
- } else
- if (!strcmp(word, "login")) {
- printf("USER %s\n", getword());
- waitreply(1);
- printf("PASS %s\n", getword());
- waitreply(1);
- } else printf("NOOP\n");
- return ret;
-}
-
-static void parseoutput(void) {
- while(!feof(stdin)) {
- sleep(1);
- printf("TODO\n");
- }
-}
-
-static void cleanup(int foo) {
- close(ff);
- unlink(fifo);
- exit(0);
-}
-
-int main(int argc, char **argv) {
- if (argc>1) {
- signal(SIGINT, cleanup);
- fifo = argv[1];
- mkfifo(fifo, 0600);
- ff = open(fifo, O_RDONLY);
- if (ff == -1) {
- fprintf(stderr, "Cannot open fifo file.\n");
- return 1;
- }
- waitreply(1);
- while(doword(getword()));
- cleanup(0);
- } else parseoutput();
- return 0;
-}
diff --git a/src/smtp.c b/src/smtp.c
@@ -1,3 +0,0 @@
-int main() {
- return 0;
-}