dmc

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

commit 28434f1cc56abb6ca58a4b2707db72775dacd4ce
parent 12a467cef4d2f1bf05a97ba4098cc5ff3d1174b7
Author: pancake@flubox <unknown>
Date:   Mon,  2 Nov 2009 13:54:01 +0100

* Tabify imap4, pop3 and dmc
* Show messages and so to stdout instead of stderr
  - Fixes .lock usage in daemon mode when error occurs
* Fix build of pop3.c
* Fix dmc -a $EDITOR related bug
Diffstat:
dmc | 447++++++++++++++++++++++++++++++++++++++++---------------------------------------
imap4.c | 4++--
pack.c | 252++++++++++++++++++++++++++++++++++++++++----------------------------------------
pop3.c | 6+++---
4 files changed, 355 insertions(+), 354 deletions(-)

diff --git a/dmc b/dmc @@ -6,278 +6,279 @@ VERSION="0.1" COPYRIGHT="Copyleft -- pancake@nopcode.org" HELP="Usage: dmc [-hv] [-e acc] [-a addr] [-m addr subj] [-A file] [-s msg] [action]" -[ -n "${EDITOR}" ] && EDITOR=vim +[ -z "${EDITOR}" ] && EDITOR=vim mkdir -p ~/.dmc/mail mkdir -p ~/.dmc/tmp mkdir -p ~/.dmc/acc [ -e ~/.dmc/acc.default ] && . ~/.dmc/acc.default acc_daemon () { - LOCK=~/.dmc/tmp/${NAME}.lock - INPUT=~/.dmc/tmp/${NAME}.input - OUTPUT=~/.dmc/tmp/${NAME}.output + LOCK=~/.dmc/tmp/${NAME}.lock + INPUT=~/.dmc/tmp/${NAME}.input + OUTPUT=~/.dmc/tmp/${NAME}.output - echo "Starting $NAME account $PROTOCOL daemon..." + echo "Starting $NAME account $PROTOCOL daemon..." - rm -f "${LOCK}" "${INPUT}" "${OUTPUT}" - mkfifo "${LOCK}" "${INPUT}" + rm -f "${LOCK}" "${INPUT}" "${OUTPUT}" + mkfifo "${LOCK}" "${INPUT}" - ( head -n 1 ${LOCK} ; dmc_cmd "login ${USER} ${PASS}" ) & - (while : ; do cat ${INPUT} 2> /dev/null ; done) | \ - dmc-${PROTOCOL} ${HOST} ${PORT} ${SSL} 2> ${OUTPUT} > ${LOCK} - rm -f "${LOCK}" "${INPUT}" "${OUTPUT}" + ( head -n 1 ${LOCK} ; dmc_cmd "login ${USER} ${PASS}" ) & + (while : ; do cat ${INPUT} 2> /dev/null ; done) | \ + dmc-${PROTOCOL} ${HOST} ${PORT} ${SSL} 2> ${OUTPUT} > ${LOCK} + rm -f "${LOCK}" "${INPUT}" "${OUTPUT}" } dmc_cmd () { - echo "$@" > ~/.dmc/tmp/${NAME}.input - head -n 1 ~/.dmc/tmp/${NAME}.lock > /dev/stderr - cat ~/.dmc/tmp/${NAME}.output + echo "$@" > ~/.dmc/tmp/${NAME}.input + head -n 1 ~/.dmc/tmp/${NAME}.lock > /dev/stderr + cat ~/.dmc/tmp/${NAME}.output } start_account_daemons () { - i=0 - for a in ~/.dmc/acc/* ; do - ( . $a ; acc_daemon ) & - i=$(($i+1)) - sleep 1 - done - if [ "$i" = 0 ]; then - echo "No accounts defined in ~/.dmc/acc" - exit 1 - fi + i=0 + for a in ~/.dmc/acc/* ; do + ( . $a ; acc_daemon ) & + i=$(($i+1)) + sleep 1 + done + if [ "$i" = 0 ]; then + echo "No accounts defined in ~/.dmc/acc" + exit 1 + fi } print_account_template () { - echo "NAME='test'" - echo "SSL=0" - echo "LIMIT=50 # get only 50 mails for each folder" - echo "PROTOCOL='pop3' # imap4" - echo "HOST=serverhost.com" - echo "PORT=110" - echo "#SEND=acc-name" - echo "SEND=!msmtp" - echo "MAIL=username@domain" - echo "USER='username'" - echo "PASS='password'" + echo "NAME='test'" + echo "SSL=0" + echo "LIMIT=50 # get only 50 mails for each folder" + echo "PROTOCOL='pop3' # imap4" + echo "HOST=serverhost.com" + echo "PORT=110" + echo "#SEND=acc-name" + echo "SEND=!msmtp" + echo "MAIL=username@domain" + echo "USER='username'" + echo "PASS='password'" } edit_message () { - OUTDIR=~/.dmc/box/${NAME}/out - mkdir -p ${OUTDIR} - OUT="`mktemp ${OUTDIR}/mail.XXXXXX`" - echo "X-Mailer: dmc v${VERSION}" > $OUT - echo "From: ${MAIL}" >> $OUT - echo "To: ${TO}" >> $OUT - echo "Subject: ${SUBJECT}" >> $OUT - echo "" >> $OUT - echo "" >> $OUT - if [ -e ~/.dmc/box/${NAME}/signature ]; then - echo "---" >> $OUT - cat ~/.dmc/box/${NAME}/signature >> $OUT - else - if [ -e ~/.dmc/signature ]; then - echo "---" >> $OUT - cat ~/.dmc/signature >> $OUT - fi - fi - ${EDITOR} ${OUT} - if [ -z "`cat ${OUT}`" ]; then - echo "Mail aborted" - rm -f "${OUT}" - else - ln -fs "${OUT}" ~/.dmc/mail.last - fi + OUTDIR=~/.dmc/box/${NAME}/out + mkdir -p ${OUTDIR} + OUT="`mktemp ${OUTDIR}/mail.XXXXXX`" + echo "X-Mailer: dmc v${VERSION}" > $OUT + echo "From: ${MAIL}" >> $OUT + echo "To: ${TO}" >> $OUT + echo "Subject: ${SUBJECT}" >> $OUT + echo "" >> $OUT + echo "" >> $OUT + if [ -e ~/.dmc/box/${NAME}/signature ]; then + echo "---" >> $OUT + cat ~/.dmc/box/${NAME}/signature >> $OUT + else + if [ -e ~/.dmc/signature ]; then + echo "---" >> $OUT + cat ~/.dmc/signature >> $OUT + fi + fi + ${EDITOR} ${OUT} + if [ -z "`cat ${OUT}`" ]; then + echo "Mail aborted" + rm -f "${OUT}" + else + ln -fs "${OUT}" ~/.dmc/mail.last + fi } add_attachment () { - OUT="`readlink ~/.dmc/mail.last`" - if [ -z "${OUT}" ]; then - echo "No ~/.dmc/mail.last found. 'dmc -m' or manual symlink required." - else - mkdir -p "${OUT}.d" - if [ -f "$1" ]; then - FILE="`basename \"$1\"`" - ln -fs "$1" "${OUT}.d/${FILE}" - else - echo "Cannot find \⅛$1\"" - fi - fi + OUT="`readlink ~/.dmc/mail.last`" + if [ -z "${OUT}" ]; then + echo "No ~/.dmc/mail.last found. 'dmc -m' or manual symlink required." + else + mkdir -p "${OUT}.d" + if [ -f "$1" ]; then + FILE="`basename \"$1\"`" + ln -fs "$1" "${OUT}.d/${FILE}" + else + echo "Cannot find \⅛$1\"" + fi + fi } send_message () { - FILE=$1 - if [ ! -e "${FILE}" ]; then - echo "Cannot find '${FILE}'" - exit 1 - fi - # TODO: find better name for the auto mode - if [ "${SEND}" = "!msmtp" ]; then - TO="`dmc -H To < $FILE`" - SJ="`dmc -H Subject < $FILE`" - echo "Sending mail to $TO (${SJ})..." -# HOST=`dmc-smtp ${TO}` - msmtp "--user=${USER}" "--from=${MAIL}" $TO < ${FILE} - return $? - elif [ "`echo \"${SEND}\" | grep '|'`" ]; then - echo "=> cat $1 ${SEND}" - # TODO: setup environment for $TO $SUBJECT ... - eval cat $1 ${SEND} - else - echo "SEND method '${SEND}' not supported" - fi - return 0 + FILE=$1 + if [ ! -e "${FILE}" ]; then + echo "Cannot find '${FILE}'" + exit 1 + fi + # TODO: find better name for the auto mode + if [ "${SEND}" = "!msmtp" ]; then + TO="`dmc -H To < $FILE`" + SJ="`dmc -H Subject < $FILE`" + echo "Sending mail to $TO (${SJ})..." +# HOST=`dmc-smtp ${TO}` + msmtp "--user=${USER}" "--from=${MAIL}" $TO < ${FILE} + return $? + elif [ "`echo \"${SEND}\" | grep '|'`" ]; then + echo "=> cat $1 ${SEND}" + # TODO: setup environment for $TO $SUBJECT ... + eval cat $1 ${SEND} + else + echo "SEND method '${SEND}' not supported" + fi + return 0 } pull_mails () { - echo "Pulling mails from account '${NAME}'" - # This is pop3-only - i=1 - while [ ! "$LIMIT" = "$i" ] ; do - dmc -c cat $i > ~/.dmc/box/${NAME}/in/$i.eml 2> ~/.dmc/tmp/${NAME}.tmp - if [ -n "`cat ~/.dmc/tmp/${NAME}.tmp | grep 'cat 0'`" ]; then - rm -f ~/.dmc/box/${NAME}/in/$i.eml - echo "EOF $i" - cat ~/.dmc/tmp/${NAME}.tmp - break - else - size=`du -hs ~/.dmc/box/${NAME}/in/$i.eml | awk '{print \$1}'` - echo "got $i $size $(cat ~/.dmc/tmp/${NAME}.tmp)" - fi - i=$(($i+1)) - done + echo "Pulling mails from account '${NAME}'" + # This is pop3-only + i=1 + while [ ! "$LIMIT" = "$i" ] ; do + dmc -c cat $i > ~/.dmc/box/${NAME}/in/$i.eml 2> ~/.dmc/tmp/${NAME}.tmp + if [ -n "`cat ~/.dmc/tmp/${NAME}.tmp | grep 'cat 0'`" ]; then + rm -f ~/.dmc/box/${NAME}/in/$i.eml + echo "EOF $i" + cat ~/.dmc/tmp/${NAME}.tmp + break + else + size=`du -hs ~/.dmc/box/${NAME}/in/$i.eml | awk '{print \$1}'` + echo "got $i $size $(cat ~/.dmc/tmp/${NAME}.tmp)" + fi + i=$(($i+1)) + done } ign () { : ; } case "$1" in "start") - start_account_daemons - ;; + start_account_daemons + ;; "stop") - cd ~/.dmc/tmp - for a in *.input ; do - [ "$a" = "*.input" ] && break # XXX ugly hack - file=`echo $a|cut -d '.' -f 1` - echo Stopping $file daemon - echo exit > $a & - sleep 1 - rm -f ~/.dmc/tmp/$a - done - rm -f ~/.dmc/tmp/* 2> /dev/null - pkill cat - trap ign TERM - pkill -TERM dmc - ;; + cd ~/.dmc/tmp + for a in *.input ; do + [ "$a" = "*.input" ] && break # XXX ugly hack + file=`echo $a|cut -d '.' -f 1` + echo Stopping $file daemon + echo exit > $a & + sleep 1 + rm -f ~/.dmc/tmp/$a + done + rm -f ~/.dmc/tmp/* 2> /dev/null + pkill cat + trap ign TERM + pkill -TERM dmc + ;; "push") - for a in ~/.dmc/acc/* ; do - . $a - if [ -d ~/.dmc/box/${NAME}/out ]; then - for b in ~/.dmc/box/${NAME}/out/* ; do - if [ -f "$b" ]; then - send_message "$b" - if [ $? = 0 ]; then - echo "Mail sent. local copy moved to ~/.dmc/box/${NAME}/sent" - mkdir -p ~/.dmc/box/${NAME}/sent - mv $b ~/.dmc/box/${NAME}/sent - else - echo "There was an error while sending the mail" - fi - fi - done - fi - done - ;; + for a in ~/.dmc/acc/* ; do + . $a + if [ -d ~/.dmc/box/${NAME}/out ]; then + for b in ~/.dmc/box/${NAME}/out/* ; do + if [ -f "$b" ]; then + send_message "$b" + if [ $? = 0 ]; then + echo "Mail sent. local copy moved to ~/.dmc/box/${NAME}/sent" + mkdir -p ~/.dmc/box/${NAME}/sent + mv $b ~/.dmc/box/${NAME}/sent + else + echo "There was an error while sending the mail" + fi + fi + done + fi + done + ;; "pull") - for a in ~/.dmc/acc/* ; do - . $a - mkdir -p ~/.dmc/box/${NAME}/in - pull_mails - done - ;; + for a in ~/.dmc/acc/* ; do + . $a + mkdir -p ~/.dmc/box/${NAME}/in + pull_mails + done + ;; "-e"|"--edit") - if [ -n "$2" ]; then - [ -z "`cat ~/.dmc/acc/$2`" ] && \ - print_account_template "$2" > ~/.dmc/acc/$2 - ${EDITOR} ~/.dmc/acc/$2 - if [ -z "`cat ~/.dmc/acc/$2`" ]; then - rm -f ~/.dmc/acc/$2 - else - echo "The '$2' account is now the default" - ln -fs ~/.dmc/acc/$2 ~/.dmc/acc.default - fi - else - ls ~/.dmc/acc | cat - fi - ;; + if [ -n "$2" ]; then + [ -z "`cat ~/.dmc/acc/$2`" ] && \ + print_account_template "$2" > ~/.dmc/acc/$2 + ${EDITOR} ~/.dmc/acc/$2 + if [ -z "`cat ~/.dmc/acc/$2`" ]; then + rm -f ~/.dmc/acc/$2 + else + echo "The '$2' account is now the default" + ln -fs ~/.dmc/acc/$2 ~/.dmc/acc.default + fi + else + ls ~/.dmc/acc | cat + fi + ;; "-H"|"--header") - if [ -z "$2" ]; then - echo "Usage: dmc -H [header] < mail" - else - grep -e : | grep -re "^$2:" | cut -d : -f 2- | sed 's, ,,' - fi - ;; + if [ -z "$2" ]; then + echo "Usage: dmc -H [header] < mail" + else + grep -e : | grep -re "^$2:" | cut -d : -f 2- | sed 's, ,,' + fi + ;; "-c"|"--cmd") - if [ -z "$2" ]; then - while : ; do - printf "> " - read A - dmc_cmd "$A" - [ "$A" = "exit" ] && exit 0 - done - else - shift - dmc_cmd "$@" - fi - ;; + if [ -z "$2" ]; then + while : ; do + printf "> " + read A + dmc_cmd "$A" + [ "$A" = "exit" ] && exit 0 + done + else + shift + dmc_cmd "$@" + fi + ;; "-s"|"--send") - shift - for a in $* ; do - send_message $a - done - ;; + shift + for a in $* ; do + send_message $a + done + ;; "-m"|"--mail") - TO="$2" - SUBJECT="$3" - edit_message - ;; + TO="$2" + SUBJECT="$3" + edit_message + ;; "-A"|"--add-attachment") - while [ -n "$2" ] ; do - add_attachment $2 - shift - done - ;; + while [ -n "$2" ] ; do + add_attachment $2 + shift + done + ;; "-a"|"--addr") - if [ -n "$2" ]; then - while [ -n "$2" ] ; do - grep -e "$2" ~/.dmc/addrbook - shift - done - else - ${EDITOR} ~/.dmc/addrbook - fi - ;; + if [ -n "$2" ]; then + while [ -n "$2" ] ; do + grep -e "$2" ~/.dmc/addrbook + shift + done + else + [ ! -f ~/.dmc/addrbook ] && touch ~/.dmc/addrbook + ${EDITOR} ~/.dmc/addrbook + fi + ;; "-v"|"--version") - echo "dmc v${VERSION} ${COPYRIGHT}" - ;; + echo "dmc v${VERSION} ${COPYRIGHT}" + ;; "--help"|"-h") - echo ${HELP} - echo " -e account edit account information" - echo " -a name show addressbook email for contact" - echo " -A file add attachment to mail" - echo " -c cmd run command for \$DMC_ACCOUNT or acc.default daemon" - echo " -m addr subj create mail with default account" - echo " -H header grep for header" - echo " -s file send email" - echo " -v show version" - echo " -h show this help message" - echo " start start mail daemons" - echo " stop stop them all" - echo " push send mails in box/*/out" - echo " pull update box/*/in folders" - ;; + echo ${HELP} + echo " -e account edit account information" + echo " -a name show addressbook email for contact" + echo " -A file add attachment to mail" + echo " -c cmd run command for \$DMC_ACCOUNT or acc.default daemon" + echo " -m addr subj create mail with default account" + echo " -H header grep for header" + echo " -s file send email" + echo " -v show version" + echo " -h show this help message" + echo " start start mail daemons" + echo " stop stop them all" + echo " push send mails in box/*/out" + echo " pull update box/*/in folders" + ;; *) - echo "${HELP}" - ;; + echo "${HELP}" + ;; esac exit 0 diff --git a/imap4.c b/imap4.c @@ -198,7 +198,7 @@ int main (int argc, char **argv) { waitreply (); dir = strdup (""); while (doword (getword ())); - } else fprintf (stderr, "Cannot connect to %s %d\n", argv[1], atoi (argv[2])); - } else fprintf(stderr, "Usage: dmc-imap4 host port 2> body > fifo < input\n"); + } else printf ("Cannot connect to %s %d\n", argv[1], atoi (argv[2])); + } else printf ("Usage: dmc-imap4 host port 2> body > fifo < input\n"); return ret; } diff --git a/pack.c b/pack.c @@ -9,144 +9,144 @@ static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01 static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; void b64_encode(unsigned char in[3], unsigned char out[4], int len) { - out[0] = cb64[ in[0] >> 2 ]; - out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; - out[2] = (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='); - out[3] = (len > 2 ? cb64[ in[2] & 0x3f ] : '='); + out[0] = cb64[ in[0] >> 2 ]; + out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; + out[2] = (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='); + out[3] = (len > 2 ? cb64[ in[2] & 0x3f ] : '='); } int b64_decode(unsigned char in[4], unsigned char out[3]) { - unsigned char len = 3, i, v[4]; - for(i=0;i<4;i++) { - if (in[i]<43||in[i]>122) - return -1; - v[i] = cd64[in[i]-43]; - if (v[i]!='$') v[i]-=62; - else { len = i-1; break; } - } - out[0] = v[0] << 2 | v[1] >> 4; - out[1] = v[1] << 4 | v[2] >> 2; - out[2] = ((v[2] << 6) & 0xc0) | v[3]; - return len; + unsigned char len = 3, i, v[4]; + for(i=0;i<4;i++) { + if (in[i]<43||in[i]>122) + return -1; + v[i] = cd64[in[i]-43]; + if (v[i]!='$') v[i]-=62; + else { len = i-1; break; } + } + out[0] = v[0] << 2 | v[1] >> 4; + out[1] = v[1] << 4 | v[2] >> 2; + out[2] = ((v[2] << 6) & 0xc0) | v[3]; + return len; } void mime_pack(char **files, int nfiles) { - FILE *fd = NULL; - char b[1024], cmd[1024], *ptr = NULL; - unsigned char bd[1024]; - int header = 1, len, in, out, i; + FILE *fd = NULL; + char b[1024], cmd[1024], *ptr = NULL; + unsigned char bd[1024]; + int header = 1, len, in, out, i; - memset (b, '\0', 1024); - while(fgets (b, 1023, stdin)) { - if (header && b[0] == '\n') { - printf ("Content-Type: multipart/mixed; boundary=\"dmc-multipart\"\n\n" - "--dmc-multipart\n" - "Content-Type: text/plain\n"); - header = 0; - } - fputs (b, stdout); - } - for(i = 0; i < nfiles; i++) { - snprintf (cmd, 1023, "file -i \"%s\"", files[i]); - if (!(fd=popen (cmd, "r"))) - continue; - fgets (b, 1023, fd); - pclose (fd); - if (!(ptr = strchr(b, ' '))) - continue; - if (!(fd=fopen(files[i], "r"))) - continue; - puts ("--dmc-multipart"); - printf ("Content-Type: %s\n", ptr+1); - printf ("Content-Disposition: attachment; filename=\"%s\"\n", files[i]); - if (strstr (ptr, "text")) { - printf("Content-Transfer-Encoding: quoted-printable\n\n"); - while (fgets(b, 1023, fd)) - printf("%s", b); - } else { - puts ("Content-Transfer-Encoding: base64\n"); - while ((len=fread(b, 1, 57, fd))) { - memset(bd,'\0',1024); - for(in=out=0;in<len;in+=3,out+=4) - b64_encode((unsigned char*)b+in,bd+out,len-in>3?3:len-in); - puts ((char *)bd); - } - } - fclose (fd); - } - puts ("--dmc-multipart--"); + memset (b, '\0', 1024); + while(fgets (b, 1023, stdin)) { + if (header && b[0] == '\n') { + printf ("Content-Type: multipart/mixed; boundary=\"dmc-multipart\"\n\n" + "--dmc-multipart\n" + "Content-Type: text/plain\n"); + header = 0; + } + fputs (b, stdout); + } + for(i = 0; i < nfiles; i++) { + snprintf (cmd, 1023, "file -i \"%s\"", files[i]); + if (!(fd=popen (cmd, "r"))) + continue; + fgets (b, 1023, fd); + pclose (fd); + if (!(ptr = strchr(b, ' '))) + continue; + if (!(fd=fopen(files[i], "r"))) + continue; + puts ("--dmc-multipart"); + printf ("Content-Type: %s\n", ptr+1); + printf ("Content-Disposition: attachment; filename=\"%s\"\n", files[i]); + if (strstr (ptr, "text")) { + printf("Content-Transfer-Encoding: quoted-printable\n\n"); + while (fgets(b, 1023, fd)) + printf("%s", b); + } else { + puts ("Content-Transfer-Encoding: base64\n"); + while ((len=fread(b, 1, 57, fd))) { + memset(bd,'\0',1024); + for(in=out=0;in<len;in+=3,out+=4) + b64_encode((unsigned char*)b+in,bd+out,len-in>3?3:len-in); + puts ((char *)bd); + } + } + fclose (fd); + } + puts ("--dmc-multipart--"); } void mime_unpack (int xtr) { - FILE *fd = NULL; - char b[1024], boundary[1024], encoding[1024], filename[1024], *ptr = NULL; - unsigned char bd[1024]; - int entity = 0, dump = 0, len, in, out, i; + FILE *fd = NULL; + char b[1024], boundary[1024], encoding[1024], filename[1024], *ptr = NULL; + unsigned char bd[1024]; + int entity = 0, dump = 0, len, in, out, i; - boundary[0] = encoding[0] = filename[0] = '\0'; - memset (b, '\0', 1024); - while (fgets(b, 1023, stdin)) { - if (!memcmp(b, "--", 2)) { - if (boundary[0] && strstr(b, boundary) && - !memcmp(b+strlen(b)-3, "--", 2)) { - entity = 0; - dump = 0; - } else { - strncpy(boundary, b+2, 1023); - if ((len = strlen(boundary)) > 0) - boundary[len-1] = '\0'; - if (fgets(b, 1023, stdin) && strstr(b, "Content-Type:")) { - entity = 1; - dump = 0; - } - } - } - if (entity) { - if ((ptr = strstr(b, "Content-Transfer-Encoding:"))) { - strncpy(encoding, ptr+26, 1023); - } else if ((ptr = strstr(b, "filename="))) { - strncpy(filename, ptr+10, 1023); - if ((len=strlen(filename)) > 1) - filename[len-2] = '\0'; - } else if (b[0] == '\n') { - if (xtr) { - if (!dump && filename[0] && (fd = fopen(filename, "w"))) { - printf("%s\n", filename); - dump = 1; - continue; - } else if (dump && strstr(encoding, "base64")) - dump = 0; - } else { - if (!dump && filename[0]) - puts (filename); - } - } - } else boundary[0] = '\0'; - if (dump) { - if (strstr(encoding, "base64")) { - memset(bd,'\0',1024); - if ((len = strlen(b)) > 0) - b[len-1] = '\0'; - for(in=out=0;in<len-1;in+=4) - out+=b64_decode((unsigned char*)b+in,bd+out); - for(i=0;i<out;i++) - fputc(bd[i], fd); - } else fputs(b, fd); - } else if (fd) { - fclose(fd); - fd = NULL; - encoding[0] = filename[0] = '\0'; - } - } + boundary[0] = encoding[0] = filename[0] = '\0'; + memset (b, '\0', 1024); + while (fgets(b, 1023, stdin)) { + if (!memcmp(b, "--", 2)) { + if (boundary[0] && strstr(b, boundary) && + !memcmp(b+strlen(b)-3, "--", 2)) { + entity = 0; + dump = 0; + } else { + strncpy(boundary, b+2, 1023); + if ((len = strlen(boundary)) > 0) + boundary[len-1] = '\0'; + if (fgets(b, 1023, stdin) && strstr(b, "Content-Type:")) { + entity = 1; + dump = 0; + } + } + } + if (entity) { + if ((ptr = strstr(b, "Content-Transfer-Encoding:"))) { + strncpy(encoding, ptr+26, 1023); + } else if ((ptr = strstr(b, "filename="))) { + strncpy(filename, ptr+10, 1023); + if ((len=strlen(filename)) > 1) + filename[len-2] = '\0'; + } else if (b[0] == '\n') { + if (xtr) { + if (!dump && filename[0] && (fd = fopen(filename, "w"))) { + printf("%s\n", filename); + dump = 1; + continue; + } else if (dump && strstr(encoding, "base64")) + dump = 0; + } else { + if (!dump && filename[0]) + puts (filename); + } + } + } else boundary[0] = '\0'; + if (dump) { + if (strstr(encoding, "base64")) { + memset(bd,'\0',1024); + if ((len = strlen(b)) > 0) + b[len-1] = '\0'; + for(in=out=0;in<len-1;in+=4) + out+=b64_decode((unsigned char*)b+in,bd+out); + for(i=0;i<out;i++) + fputc(bd[i], fd); + } else fputs(b, fd); + } else if (fd) { + fclose(fd); + fd = NULL; + encoding[0] = filename[0] = '\0'; + } + } } int main(int argc, char **argv) { - if (argc < 2 || !strcmp(argv[1], "-h")) - fprintf (stderr, "Usage: %s [-hlu | attachment1 attachment2...] < mail\n", argv[0]); - else if (!strcmp(argv[1], "-l")) - mime_unpack (0); - else if (!strcmp(argv[1], "-u")) - mime_unpack (1); - else mime_pack(argv+1, argc-1); - return 0; + if (argc < 2 || !strcmp(argv[1], "-h")) + printf ("Usage: %s [-hlu | attachment1 attachment2...] < mail\n", argv[0]); + else if (!strcmp(argv[1], "-l")) + mime_unpack (0); + else if (!strcmp(argv[1], "-u")) + mime_unpack (1); + else mime_pack(argv+1, argc-1); + return 0; } diff --git a/pop3.c b/pop3.c @@ -39,7 +39,7 @@ static int waitreply (int res) { if (!ch) ch = strchr (str, '\n'); if (ch) { - reply = (word[0] == '+') + reply = (word[0] == '+'); *ch = 0; snprintf (result, 1023, "### %s %d \"%s\"\n", cmd, reply, str); str = ch+((ch[1]=='\n')?2:1); @@ -111,7 +111,7 @@ int main(int argc, char **argv) { atexit (sock_close); waitreply (1); while (doword (getword ())); - } else fprintf (stderr, "Cannot connect to %s %d\n", argv[1], atoi(argv[2])); - } else fprintf (stderr, "Usage: dmc-pop3 host port [ssl] 2> body > fifo < input\n"); + } else printf ("Cannot connect to %s %d\n", argv[1], atoi(argv[2])); + } else printf ("Usage: dmc-pop3 host port [ssl] 2> body > fifo < input\n"); return 0; }