commit 43eaf431363a563976bc93d3b69df5f80cbac5ba
parent 408e8287b667c34daae6513a0815b649118ff65a
Author: pancake <nopcode.org>
Date: Mon, 10 May 2010 00:16:18 +0200
* Implement -r and -f to reply and forward mails
* [FWD|REG]|[MSG|SUB] in config.def.h to configure messages
* evalstr() filters subject and reply/forward message
* Commands are now stored in global DmcQuery reply
* Create all basic home directories in -e
Diffstat:
TODO | | | 8 | +++----- |
config.def.h | | | 4 | ++++ |
dmc.c | | | 223 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ |
3 files changed, 180 insertions(+), 55 deletions(-)
diff --git a/TODO b/TODO
@@ -1,11 +1,9 @@
TODO
----
+* PULL METHOD:
+* lsd ! cd - ; ls ! get 1
+---
* Make it more fail-fast (use exit, instead of free)
-* how to reply a mail?
- - dmc -r [mail] [addr]
- -> runs dmc-filter -b < mail | sed -e 's,^,> ,'
-* how to forward a mail?
- - dmc -f [mail] [addr]
* Create a mail with attachments (dmc -m addr subject file1 file2 file3 ..)
* Attach file to given mail (not last one)
* Define a list of 'subscribed' folders for IMAP ~/.dmc/box/.folders ?
diff --git a/config.def.h b/config.def.h
@@ -3,3 +3,7 @@
#define DIRPERM 0750
#define EDITOR "vim"
#define MAXACC 16 /* maximum number of accounts */
+#define FWDMSG "Begin forwarded message:\n"
+#define REPMSG "On {Date: }, {From: } wrote:\n"
+#define FWDSUB "Fwd: "
+#define REPSUB "Re: "
diff --git a/dmc.c b/dmc.c
@@ -18,10 +18,19 @@ static int dmc_in[2], dmc_out[2], dmc_err[2];
static int dmc_pid = -1;
static fd_set rfds, wfds;
+typedef struct {
+ char *out;
+ char *err;
+ int errlen;
+} DmcQuery;
+
+static DmcQuery reply;
+
static void dmcstop();
static int dmcsend(const char *file);
static int fexist(const char *path);
+#if 0
static char *dmcnamegen(const char *file) {
// return filename from mail
// Name is YYYYMMDDhhmm## -- name sort by date
@@ -31,11 +40,39 @@ static char *dmcnamegen(const char *file) {
return NULL;
}
+static int dmcstore() {
+ // TODO
+ return 0;
+}
+#endif
+
+static const char *dmcalias(const char *filter) {
+ static char line[64];
+ FILE *fd = fopen (DMCDIR"/addrbook", "r");
+ if (fd) {
+ for (;;) {
+ fgets (line, sizeof (line), fd);
+ if (feof (fd))
+ break;
+ if (strstr (line, filter)) {
+ line[strlen(line)-1] = 0;
+ return line;
+ }
+ }
+ fclose (fd);
+ }
+ return filter;
+}
+
static const char *dmcmailpath(const char *name) {
static char path[256];
/* check ./%s */
if (fexist (name))
return name;
+ /* check DMCDIR/box/$acc/in/%s.eml */
+ snprintf (path, sizeof (path), DMCDIR"/box/%s/in/%s.eml", defacc, name);
+ if (fexist (path))
+ return path;
/* check DMCDIR/box/$acc/in/%s */
snprintf (path, sizeof (path), DMCDIR"/box/%s/in/%s", defacc, name);
if (fexist (path))
@@ -65,6 +102,7 @@ static void dmcinit() {
defacc = acc[0];
signal (SIGINT, dmcstop);
atexit (dmcstop);
+ reply.out = reply.err = NULL;
}
static char *cfgget(const char *key) {
@@ -189,14 +227,19 @@ static void dmcstop() {
}
}
-static char *dmccmd(const char *cmd, char *err, int errlen) {
- static char buf[4096];
+static int dmccmd(const char *cmd) {
+ static char buf[128];
int ret, nfd;
if (dmc_pid == -1) {
printf ("Use 'on' or '?'\n");
- return NULL;
+ return 0;
}
+ free (reply.out);
+ reply.out = NULL;
+ free (reply.err);
+ reply.err = NULL;
+ reply.errlen = 0;
for (;;) {
FD_ZERO (&rfds);
FD_ZERO (&wfds);
@@ -210,7 +253,8 @@ static char *dmccmd(const char *cmd, char *err, int errlen) {
ret = read (dmc_out[0], buf, sizeof (buf)-1);
if (ret>0) {
buf[ret-1] = 0;
- printf ("-(out)-> (%s)\n", buf);
+ reply.out = strdup (buf); // XXX
+ //printf ("-(out)-> (%s)\n", buf);
break;
}
} else
@@ -218,7 +262,10 @@ static char *dmccmd(const char *cmd, char *err, int errlen) {
ret = read (dmc_err[0], buf, sizeof (buf)-1);
if (ret>0) {
buf[ret-1] = 0;
- printf ("-(err)-> (%s)\n", buf);
+ reply.err = realloc (reply.err, reply.errlen+ret+1);
+ memcpy (reply.err+reply.errlen, buf, ret);
+ reply.errlen += ret-1;
+ //printf ("-(err)-> (%s)\n", buf);
}
} else
if (FD_ISSET (dmc_in[1], &wfds)) {
@@ -230,7 +277,7 @@ static char *dmccmd(const char *cmd, char *err, int errlen) {
}
}
}
- return buf;
+ return 1;
}
static int dmcpull(const char *name) {
@@ -253,8 +300,10 @@ static void dmcpush(const char *name) {
printf ("%s: ", file);
fflush (stdout);
if (dmcsend (file)) {
- // TODO: remove .d
- unlink (file);
+ snprintf (path, sizeof (path),
+ "mv %s* "DMCDIR"/box/%s/sent",
+ file, defacc);
+ system (path); // do not use system()
}
}
}
@@ -329,8 +378,7 @@ static int dmcsend(const char *file) {
}
static int dmcline(const char *line) {
- char err[128], cmd[128];
- char *ptr = strchr (line, ' ');
+ char cmd[128];
if (!strcmp (line, "?")) {
printf ("Usage: on off push pull exit ls cat ..\n");
} else
@@ -338,13 +386,15 @@ static int dmcline(const char *line) {
char *user = cfgget ("USER=");
char *pass = cfgget ("PASS=");
snprintf (cmd, sizeof (cmd), "login %s %s\n", user, pass);
- ptr = dmccmd (cmd, err, sizeof (err));
+ if (!dmccmd (cmd))
+ printf ("Error.\n");
free (user);
free (pass);
} else
if (!strcmp (line, "on")) {
dmcstart (acc[0]);
- ptr = dmccmd (NULL, err, sizeof (err));
+ if (!dmccmd (NULL))
+ printf ("Error.\n");
} else
if (!strcmp (line, "off")) {
dmcstop ();
@@ -362,11 +412,9 @@ static int dmcline(const char *line) {
return 0;
} else {
/* bypass to child */
- ptr = dmccmd (line, err, sizeof (err));
- if (ptr) {
- printf ("%s\n", ptr);
- fprintf (stderr, "%s\n", err);
- //free (ptr);
+ if (dmccmd (line)) {
+ printf ("-(out)-> %s\n", reply.out);
+ printf ("-(err)-> %s\n", reply.err);
} else fprintf (stderr, "## No reply\n");
}
return 1;
@@ -374,25 +422,23 @@ static int dmcline(const char *line) {
static int usage(const char *argv0, int lon) {
fprintf (stderr, "Usage: %s [-hv] [-c [cmd] [-s file] [-e acc] [-A file ..]\n"
- "\t [-a addr] [-m [A|S A]] [-l [box]]\n", argv0);
- if (lon) {
- fprintf (stderr,
- " -m [A [S]] create mail (Address, Subject)\n"
- " -c [cmd] command shell\n"
- " -e [acc] list/edit/set default accounts\n"
- " -a [addr] grep in addressbook\n"
- " -A [file .] attach files to ~/.dmc/mail.last done by 'dmc -m'\n"
- " -l [box] list mails in specified box of def account\n"
- " -s [file] send mail\n"
- //" -f [file] forward mail\n"
- //" -r [file] reply mail\n"
- " -v show version\n"
- "");
- }
+ "\t [-a addr] [-m [a [s [..]] [-f m a] [-r m a] [-l [box]]\n", argv0);
+ if (lon) fprintf (stderr,
+ " -m [a [s]..] create mail [addr [subj [file1 file2 ..]]]\n"
+ " -c [cmd] command shell\n"
+ " -e [acc] list/edit/set default accounts\n"
+ " -a [addr] grep in addressbook\n"
+ " -A [file .] attach files to ~/.dmc/mail.last done by 'dmc -m'\n"
+ " -l [box] list mails in specified box of def account\n"
+ " -s [file] send mail\n"
+ " -f m [addr] forward mail to addr\n"
+ " -r m [addr] reply mail to addr\n"
+ " -v show version\n"
+ "");
return 0;
}
-static int dmcmail(const char *addr, const char *subj) {
+static int dmcmail(const char *addr, const char *subj, const char *slurp, const char *slurptitle) {
const char *from = cfgget("MAIL=");
char file[128], line[128];
int fd;
@@ -405,6 +451,23 @@ static int dmcmail(const char *addr, const char *subj) {
"To: %s\n"
"Subject: %s\n\n\n", from, addr, subj);
write (fd, line, strlen (line));
+ if (slurp) {
+ FILE *sfd = fopen (slurp, "r");
+ if (sfd) {
+ int body = 0;
+ write (fd, "\n\n", 2);
+ if (slurptitle)
+ write (fd, slurptitle, strlen (slurptitle));
+ for (;;) {
+ fgets (line, sizeof (line), sfd);
+ if (feof (sfd)) break;
+ if (body) {
+ write (fd, "> ", 2);
+ write (fd, line, strlen (line));
+ } else if (strlen (line)<4) body = 1;
+ }
+ }
+ }
close (fd);
snprintf (line, sizeof (line), EDITOR" %s", file);
system (line);
@@ -430,6 +493,58 @@ static void dmcattach(const char *file) {
} else fprintf (stderr, "Cannot attach '%s'\n", file);
}
+static char *evalstr(const char *mail, const char *str) {
+ int outi = 0;
+ char *out, *tmp;
+ const char *ptr = str;
+ out = malloc (1024); // XXX overflow
+ while (*ptr) {
+ if (*ptr == '{') {
+ int dsti = 0;
+ char dst[1024];
+ ptr++;
+ while (*ptr && *ptr != '}' && dsti<sizeof(dst)-1) {
+ dst[dsti++] = *ptr;
+ ptr++;
+ }
+ dst[dsti] = 0;
+ tmp = gethdr ("/", mail, dst);
+ if (tmp) {
+ strcpy (out+outi, tmp);
+ outi += strlen (tmp);
+ free (tmp);
+ }
+ ptr++;
+ continue;
+ }
+ out[outi++] = *ptr;
+ ptr++;
+ }
+ out[outi] = 0;
+ return out;
+}
+
+static void dmcfwd(const char *file, const char *addr, const char *msg, const char *sub) {
+ if (file) {
+ char *m, *subj, *msub = gethdr ("/", file, "Subject: ");
+ if (msub) {
+ char *s = evalstr (file, sub);
+ subj = malloc (strlen (msub) + strlen (s) + 2);
+ strcpy (subj, s);
+ strcat (subj, msub);
+ free (s);
+ } else {
+ subj = strdup (sub);
+ }
+ if (addr && *addr)
+ addr = dmcalias (addr);
+ m = evalstr (file, msg);
+ dmcmail (addr, subj, file, m);
+ free (m);
+ free (subj);
+ } else fprintf (stderr, "Mail not found.\n");
+}
+
int main(int argc, char **argv) {
char file[128], line[128];
struct dirent *de;
@@ -487,13 +602,17 @@ int main(int argc, char **argv) {
break;
case 'm':
{
- char *addr = "";
- char *subj = "";
+ const char *addr = "";
+ const char *subj = "";
if (argc>2)
addr = argv[2];
if (argc>3)
subj = argv[3];
- dmcmail (addr, subj);
+ if (addr && !strchr (addr, '@'))
+ addr = dmcalias (addr);
+ if (dmcmail (addr, subj, NULL, NULL))
+ for (i=4; argv[i]; i++)
+ dmcattach (argv[i]);
}
break;
case 'e':
@@ -532,6 +651,14 @@ int main(int argc, char **argv) {
printf ("Default account has changed.\n");
unlink (DMCDIR"/acc.default");
symlink (file, DMCDIR"/acc.default");
+ snprintf (line, sizeof (line), DMCDIR"/box/%s", argv[2]);
+ mkdir (line, DIRPERM);
+ snprintf (line, sizeof (line), DMCDIR"/box/%s/out", argv[2]);
+ mkdir (line, DIRPERM);
+ snprintf (line, sizeof (line), DMCDIR"/box/%s/in", argv[2]);
+ mkdir (line, DIRPERM);
+ snprintf (line, sizeof (line), DMCDIR"/box/%s/sent", argv[2]);
+ mkdir (line, DIRPERM);
}
}
break;
@@ -540,19 +667,9 @@ int main(int argc, char **argv) {
snprintf (line, sizeof (line), EDITOR" '"DMCDIR"/addrbook'");
system (line);
} else {
- FILE *fd = fopen (DMCDIR"/addrbook", "r");
- if (fd) {
- for (;;) {
- fgets (line, sizeof (line), fd);
- if (feof (fd))
- break;
- for (i=2; i<argc; i++) {
- if (strstr (line, argv[i]))
- printf ("%s", line);
- }
- }
- fclose (fd);
- }
+ const char *mail = dmcalias (argv[2]);
+ if (mail)
+ puts (mail);
}
break;
case 'c':
@@ -567,11 +684,17 @@ int main(int argc, char **argv) {
} while (dmcline (line));
} else {
strcpy (prompt, "");
- for(i=2; i<argc; i++)
+ for (i=2; i<argc; i++)
dmcline (argv[i]);
}
dmcstop ();
break;
+ case 'r': // reply
+ dmcfwd (dmcmailpath (argv[2]), argc>3?argv[3]:"", REPMSG, REPSUB);
+ break;
+ case 'f': // forward
+ dmcfwd (dmcmailpath (argv[2]), argc>3?argv[3]:"", FWDMSG, FWDSUB);
+ break;
default:
return usage (argv[0], 1);
}