dmc

dynamic mail client
git clone git://git.suckless.org/dmc
Log | Files | Refs | README | LICENSE

commit 0288b48f2b47ad004b6b17020a238c1c371d868e
parent 625edc38d5fcd59e99432a53e483abb53672e057
Author: pancake <nopcode.org>
Date:   Sun,  2 May 2010 03:39:17 +0200

* Initial import of dmc-cmd .. ongoing replacement in C
  of the 'dmc' command.
* added 'dmc -l' to list folders and show mails
* some random fixes and code cleanup in pop3 and imap4
  - try to avoid the use of heap
  - sizeof buffers to avoid mistakes
Diffstat:
Makefile | 5++++-
README | 1+
dmc | 21++++++++++++++++++++-
dmc-cmd.c | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
filter.c | 8++++----
imap4.c | 30+++++++++++++-----------------
pop3.c | 27+++++++++++++--------------
sock.c | 8+++-----
8 files changed, 118 insertions(+), 42 deletions(-)

diff --git a/Makefile b/Makefile @@ -8,10 +8,13 @@ endif CFLAGS+=-DHAVE_SSL=${HAVE_SSL} CFLAGS+=-DVERSION=\"${VERSION}\" -BINS=dmc-mbox dmc-smtp dmc-pop3 dmc-imap4 dmc-pack dmc-filter dmc-mbox +BINS=dmc-cmd dmc-mbox dmc-smtp dmc-pop3 dmc-imap4 dmc-pack dmc-filter dmc-mbox all: ${BINS} +dmc-cmd: dmc-cmd.o + ${CC} dmc-cmd.o -o dmc-cmd + dmc-smtp: smtp.o ${CC} ${LDFLAGS} smtp.o -o dmc-smtp -lresolv diff --git a/README b/README @@ -90,3 +90,4 @@ TODO * Attach file to mail without hacky commands * Define a list of 'subscribed' folders for IMAP * Pull specific folder (dmc pull [folder]) +* getword() is implemented so MANY times.. MERGE! diff --git a/dmc b/dmc @@ -30,7 +30,7 @@ acc_daemon () { mkfifo "${LOCK}" "${INPUT}" # wait 1 connect message and 1 login message - (head -n 2 ${LOCK} ; dmc_cmd "login ${USER} ${PASS}" ; dmc_cmd "ls" ; ) & + (head -n 2 ${LOCK} ; dmc_cmd "login ${USER} ${PASS}" ; dmc_cmd "ls") & (while : ; do cat ${INPUT} 2> /dev/null ; done) | \ dmc-${PROTOCOL} ${HOST} ${PORT} ${SSL} 2> ${OUTPUT} > ${LOCK} rm -f "${LOCK}" "${INPUT}" "${OUTPUT}" @@ -276,6 +276,24 @@ case "$1" in ${EDITOR} ~/.dmc/addrbook fi ;; +"-l"|"--list") + cd ~/.dmc/box/${NAME}/in + if [ -n "$2" ]; then + if [ -f "$2.eml" ]; then + cat $2.eml + exit 0 + fi + cd $2 + fi + for a in `ls -rt *.eml` ; do + printf "$a:\t\x1b[32m" + dmc-filter Subject < $a | head -n 1 + printf "\x1b[0m \t- " + dmc-filter To < $a | head -n 1 + printf " \t- " + dmc-filter Date < $a | head -n 1 + done + ;; "-v"|"--version") echo "dmc v${VERSION}" ;; @@ -287,6 +305,7 @@ case "$1" in echo " -c cmd run command for \$DMC_ACCOUNT or acc.default daemon" echo " -m addr subj create mail with default account" echo " -s file send email" + echo " -l [mail/fold] list mails in folder or show mail" echo " -v show version" echo " -h show this help message" echo " start start mail daemons" diff --git a/dmc-cmd.c b/dmc-cmd.c @@ -0,0 +1,60 @@ +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +static char prompt[64]; + + +static int dmcline(const char *line) { + char *ptr = strchr (line, ' '); + if (ptr) + *ptr = '\0'; + printf ("--> (%s)\n", ptr); + if (!strcmp (line, "")) { + + } else { + /* bypass to child */ + } + return 1; +} + +int main(int argc, char **argv) { + char line[128]; + strcpy (prompt, "dmc> "); + do { + write (1, prompt, strlen (prompt)); + read (0, line, sizeof (line)); + if (feof (stdin)) + strcpy (line, "exit\n"); + } while (dmcline (line)); + return 0; +} + +#if 0 + $ echo pull | dmc-cmd + $ dmc-cmd pull + $ dmc + dmc> ls + nopcode + radare + dmc> use nopcode + # start dmc-pop3 connection + dmc/nopcode> login [user/pass] + # +OK (user/pass) are optional + dmc/nopcode> ls + +Commands +======== +Handled by dmc-cmd: + ? : alias for help + use <accountname> + pull + push + help + +Handled by dmc-pop3|imap4|...: + exit: handled by child + cd <change directory> + help + +#endif diff --git a/filter.c b/filter.c @@ -22,13 +22,13 @@ int main(int argc, char **argv) { if (!strcmp (argv[i], "-e")) edit = i; for (i = 0; i < argc; i++) { - strncpy (argv2[i], argv[i], 1023); + strncpy (argv2[i], argv[i], sizeof (argv2[i])); argv2[i][1023] = '\0'; } } - memset (b, '\0', 1024); + *b = '\0'; /* Headers */ - while (fgets (b, 1023, stdin) && b[0] != '\n') + while (fgets (b, sizeof (b), stdin) && b[0] != '\n') if ((b[0] == ' ' || b[0] == '\t')) { if (print) fputs (b, stdout); } else for (i = filter; i < edit && argv[i]; i++) @@ -58,7 +58,7 @@ int main(int argc, char **argv) { if (argv2[i][0]) puts (argv2[i]); if (edit < argc) puts (""); /* Body */ - while ((argc < 2 || edit < argc) && fgets (b, 1023, stdin)) + while ((argc < 2 || edit < argc) && fgets (b, sizeof (b), stdin)) fputs (b, stdout); } return 0; diff --git a/imap4.c b/imap4.c @@ -13,8 +13,8 @@ #include <sys/types.h> #include "sock.c" -static char *cmd = NULL; -static char word[4096]; +#define STRSZ 4095 +static char cmd[STRSZ], word[STRSZ]; static char *dir; static int ctr = 1; @@ -58,12 +58,12 @@ static int waitreply(int catmode) { int lock = 1; int line = 0; int reply = -1; - char result[1024]; + char res[1024]; ftruncate (2, 0); lseek (2, 0, SEEK_SET); - word[0] = result[0] = '\0'; - while(lock || sock_ready ()) { + word[0] = res[0] = '\0'; + while (lock || sock_ready ()) { lock = 0; memset (word, 0, 4096); if (sock_read (word, 4095) <1) @@ -91,7 +91,7 @@ static int waitreply(int catmode) { if (ptr) { char oldptr = *ptr; *ptr = '\0'; - snprintf (result, 1023, "### %s %d \"%s\"\n", cmd, reply, word); + snprintf (res, sizeof (res), "### %s %d \"%s\"\n", cmd, reply, word); *ptr = oldptr; if (catmode) { if (oldptr=='\r') @@ -114,7 +114,7 @@ static int waitreply(int catmode) { write (2, word, strlen (word)); } - write (1, result, strlen (result)); + write (1, res, strlen (res)); return reply; } @@ -129,8 +129,7 @@ RECENT - show the number of recent messages #endif static int doword(char *word) { int ret = 1; - free (cmd); - cmd = strdup (word); + strcpy (cmd, word); if (*word == '\0') { /* Do nothing */ } else @@ -162,13 +161,11 @@ static int doword(char *word) { waitreply (0); } else if (!strcmp (word, "cat")) { - sock_printf ("%d FETCH %d body[]\n", - ctr++, atoi (getword ())); + sock_printf ("%d FETCH %d body[]\n", ctr++, atoi (getword ())); waitreply (1); } else if (!strcmp (word, "head")) { - sock_printf ("%d FETCH %d body[header]\n", - ctr++, atoi (getword ())); + sock_printf ("%d FETCH %d body[header]\n", ctr++, atoi (getword ())); waitreply (1); } else if (!strcmp (word, "mvdir")) { @@ -183,15 +180,13 @@ static int doword(char *word) { waitreply (0); } else if (!strcmp (word, "rmdir")) { - printf("%d DELETE \"%s\"\n", - ctr++, getword ()); + sock_printf ("%d DELETE \"%s\"\n", ctr++, getword ()); waitreply (0); } else if (!strcmp (word, "login")) { char *user = strdup (getword ()); char *pass = strdup (getword ()); - sock_printf ("%d LOGIN \"%s\" \"%s\"\n", - ctr++, user, pass); + sock_printf ("%d LOGIN \"%s\" \"%s\"\n", ctr++, user, pass); free (user); free (pass); waitreply (0); @@ -209,6 +204,7 @@ int main (int argc, char **argv) { ssl = (*argv[3]=='1'); if (sock_connect (argv[1], atoi (argv[2]), ssl) >= 0) { ret = 0; + *cmd = 0; atexit (sock_close); waitreply (0); dir = strdup (""); diff --git a/pop3.c b/pop3.c @@ -13,8 +13,8 @@ #include <poll.h> #include "sock.c" -static char *cmd = NULL; -static char word[1024]; +#define STRSZ 4095 +static char cmd[STRSZ], word[STRSZ]; static char *getword() { fscanf (stdin, "%s", word); @@ -23,20 +23,19 @@ static char *getword() { return word; } -static int waitreply(int res) { - char result[4096]; - char *ch, *str; +static int waitreply(int foo) { + char *ch, *str, res[STRSZ]; int reply = -1; ftruncate (2, 0); lseek (2, 0, SEEK_SET); - result[0] = '\0'; - while (sock_ready () && sock_read (word, sizeof(word)) > 1) { + *res = '\0'; + while (sock_ready () && sock_read (word, sizeof (word)) > 1) { str = word; if (reply == -1 && (reply = (word[0] == '+'))) { if ((ch = strchr (str, '\r')) || (ch = strchr (str, '\n'))) { *ch = '\0'; - snprintf (result, sizeof (result), "### %s %d \"%s\"\n", cmd, reply, str); + snprintf (res, sizeof (res), "### %s %d \"%s\"\n", cmd, reply, str); str = ch + (ch[1] == '\n' ? 2 : 1); } } @@ -46,18 +45,17 @@ static int waitreply(int res) { write (2, str, strlen (str)); } write (2, "\n", 1); - if (res) { - if (result[0] == '\0') - snprintf (result, sizeof (result), "### %s %d \"\"\n", cmd, reply); - write (1, result, strlen (result)); + if (foo) { + if (!*res) + snprintf (res, sizeof (res), "### %s %d \"\"\n", cmd, reply); + write (1, res, strlen (res)); } return reply; } static int doword(char *word) { int ret = 1; - free (cmd); - cmd = strdup (word); + strcpy (cmd, word); if (*word == '\0') { /* Do nothing */ @@ -102,6 +100,7 @@ int main(int argc, char **argv) { ssl = (*argv[3] == '1'); if (sock_connect (argv[1], atoi (argv[2]), ssl) >= 0) { ret = atexit (sock_close); + strcpy (cmd, "."); waitreply (1); while (doword (getword ())); } else printf ("Cannot connect to %s %d\n", argv[1], atoi (argv[2])); diff --git a/sock.c b/sock.c @@ -31,9 +31,8 @@ int sock_ssl (int fd) { SSL_set_fd (sfd, fd); if (SSL_connect (sfd) < 1) return -1; - else #endif - return fd; + return fd; } int sock_connect(const char *host, int port, int ssl_enable) { @@ -66,7 +65,7 @@ int sock_ready() { fds[0].fd = fd; fds[0].events = POLLIN|POLLPRI; fds[0].revents = POLLNVAL|POLLHUP|POLLERR; - return poll(fds, 1, 1000); + return poll (fds, 1, 1000); } void sock_close() { @@ -81,7 +80,6 @@ int sock_write(const char *str) { #if HAVE_SSL if (ssl) return SSL_write (sfd, str, strlen(str)); - else #endif return write (fd, str, strlen(str)); } @@ -91,7 +89,7 @@ int sock_printf(const char *fmt, ...) { int ret = -1; char buf[1024]; va_start (ap, fmt); - vsnprintf (buf, 1023, fmt, ap); + vsnprintf (buf, sizeof (buf), fmt, ap); // XXX check len ret = sock_write (buf); va_end (ap);