dmc

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

commit 23994ab79d4c9e22873526f9c928f934160f8d97
parent 28ae5038608041eaee262165ac7a1576d64238be
Author: pancake <nopcode.org>
Date:   Tue, 11 May 2010 00:10:38 +0200

* Fix many errors appeared in previous commit
  - Some paths was not correctly handled
  - Simplify and refactorize a bit more
* Implemented local 'ls' and 'cat' commands
  - Split into dmccat() and dmcls()
Diffstat:
dmc.c | 160++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 98 insertions(+), 62 deletions(-)

diff --git a/dmc.c b/dmc.c @@ -61,6 +61,18 @@ static const char* wd(const char *fmt, ...) { return ret; } +static const char *abspath(const char *file) { + static char filepath[512]; + char cwd[128]; + if (*file=='/') + return file; + getcwd (cwd, sizeof (cwd)); + snprintf (filepath, sizeof (filepath)-strlen (file)-3, "%s", cwd); + strcat (filepath, "/"); + strcat (filepath, file); + return filepath; +} + static const char *dmcalias(const char *filter) { static char line[64]; FILE *fd = fopen (wd ("addrbook"), "r"); @@ -105,6 +117,62 @@ static const char *dmcmailpath(const char *name) { return NULL; } +static int dmccat(const char *file) { + char line[128]; + const char *f = dmcmailpath (file); // XXX dup? + if (f && fexist (f)) { + snprintf (line, sizeof (line), "cat '%s'", f); + system (line); // implement native cat + return 1; + } else fprintf (stderr, "Cannot find '%s'\n", file); + return 0; +} + +static char *gethdr(const char *path, const char *file, const char *hdr) { + char line[1024], *ret = NULL; + FILE *fd; + int i; + snprintf (line, sizeof (line), "%s/%s", path, file); + fd = fopen (line, "r"); + if (fd) { + int len = strlen (hdr); + while (!feof (fd)) { + fgets (line, sizeof (line), fd); + if (!memcmp (line, hdr, len)) { + i = strlen (line)-1; + if (i>len) { + line[i--] = '\0'; + if (line[i]=='\r'||line[i]=='\n') + line[i] = '\0'; + ret = strdup (line+len); + } else ret = strdup (""); + break; + } + } + fclose (fd); + } + return ret; +} + +static int dmcls(const char *path) { + struct dirent *de; + DIR *dir; + if ((dir = opendir (path))) { + while ((de = readdir (dir))) { + if (*de->d_name!='.') { + char *subj = gethdr (path, de->d_name, "Subject: "); + char *from = gethdr (path, de->d_name, "From: "); + printf ("%s:\t%s\n\t%s\n", de->d_name, subj, from); + free (from); + free (subj); + } + } + closedir (dir); + return 1; + } + return 0; +} + static void dmcinit() { char *tmp = getenv ("EDITOR"); editor = tmp? tmp: EDITOR; @@ -112,7 +180,6 @@ static void dmcinit() { fprintf (stderr, "Cannot find HOME\n"); exit (1); } - // NOTE: force home to be absolute path snprintf (dmcdir, sizeof (dmcdir), "/%s/"DMCDIR"/", tmp); if (!fexist (dmcdir)) if (mkdir (dmcdir, DIRPERM) == -1) { @@ -124,7 +191,6 @@ static void dmcinit() { mkdir (wd ("acc"), DIRPERM); acc = dmcaccounts (); defacc = acc[0]; - // signal (SIGINT, dmcstop); atexit (dmcstop); reply.out = reply.err = NULL; @@ -152,32 +218,6 @@ static char *cfgget(const char *key) { return ret; } -static char *gethdr(const char *path, const char *file, const char *hdr) { - char line[1024], *ret = NULL; - FILE *fd; - int i; - snprintf (line, sizeof (line), "%s/%s", path, file); - fd = fopen (line, "r"); - if (fd) { - int len = strlen (hdr); - while (!feof (fd)) { - fgets (line, sizeof (line), fd); - if (!memcmp (line, hdr, len)) { - i = strlen (line)-1; - if (i>len) { - line[i--] = '\0'; - if (line[i]=='\r'||line[i]=='\n') - line[i] = '\0'; - ret = strdup (line+len); - } else ret = strdup (""); - break; - } - } - fclose (fd); - } - return ret; -} - /* server */ static int dmcstart(const char *name) { char a0[512], a1[32]; @@ -315,7 +355,8 @@ static void dmcpush(const char *name) { int i; for (i=0; acc[i]; i++) { - dir = opendir (wd ("box/%s/out", acc[i])); + snprintf (path, sizeof (path), "%s/box/%s/out", dmcdir, acc[i]); + dir = opendir (path); while ((de = readdir (dir))) { char *n = de->d_name; if (*n != '.' && !strstr (n, ".d")) { @@ -333,10 +374,9 @@ static void dmcpush(const char *name) { } } -/* utils */ static int fexist(const char *path) { struct stat st; - int ret = stat (path, &st); + int ret = path? stat (path, &st): -1; return (ret != -1); } @@ -392,7 +432,6 @@ static int dmcsend(const char *file) { "dmc-pack `ls %s.d/* 2>/dev/null` < %s " "| msmtp --user=\"%s\" --from=\"%s\" \"%s\"", file, file, user, mail, to); - //printf ("LINE: %s\n", line); if (system (line) != 0) { fprintf (stderr, "Error ocurred while sending %s\n", file); return 0; @@ -403,7 +442,7 @@ static int dmcsend(const char *file) { static int dmcline(const char *line) { char cmd[128]; if (!strcmp (line, "?")) { - printf ("Usage: on off push pull exit ls cat ..\n"); + printf ("Usage: on off push pull exit ls lsd cat ..\n"); } else if (!strcmp (line, "login")) { char *user = cfgget ("USER="); @@ -422,8 +461,18 @@ static int dmcline(const char *line) { if (!strcmp (line, "off")) { dmcstop (); } else + if (!strcmp (line, "ls")) { + if (dmc_pid != -1) + dmccmd ("ls\n"); + else dmcls (wd ("box/%s/in", defacc)); + } else + if (!memcmp (line, "cat ", 4)) { + if (dmc_pid != -1) + dmccmd (line); // bypass + else dmccat (line+4); + } else if (!strcmp (line, "push")) { - dmcpush (acc[0]); + dmcpush (defacc); } else if (!strcmp (line, "pull")) { if (dmcstart (acc[0])) { @@ -445,7 +494,7 @@ 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 [..]] [-f m a] [-r m a] [-l [box]]\n", argv0); + "\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" @@ -464,10 +513,11 @@ static int usage(const char *argv0, int lon) { 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; + int fd, ret = 0; snprintf (file, sizeof (file), "%s/box/%s/out/mail.XXXXXX", dmcdir, acc[0]); fd = mkstemp (file); if (fd != -1) { + // TODO: fchmod or mkostemp snprintf (line, sizeof (line), "X-Mailer: dmc v"VERSION"\n" "From: %s\n" @@ -492,17 +542,19 @@ static int dmcmail(const char *addr, const char *subj, const char *slurp, const } } close (fd); - snprintf (line, sizeof (line), EDITOR" %s", file); + snprintf (line, sizeof (line), EDITOR" '%s'", file); system (line); if (fsize (file)<32) { fprintf (stderr, "Aborted\n"); unlink (file); } else { snprintf (line, sizeof (line), "%s/mail.last", dmcdir); + unlink (line); symlink (file, line); + ret = 1; } } else fprintf (stderr, "Cannot create '%s'\n", file); - return 0; + return ret; } static void dmcattach(const char *file) { @@ -511,11 +563,13 @@ static void dmcattach(const char *file) { while (*name!='/' && name>file) name--; name++; - if (readlink (wd ("mail.last"), path, sizeof (path)-10)!=-1) { + path[0] = 0; + memset (path, 0, sizeof(path)); + if (readlink (wd ("mail.last"), path, sizeof (path)-strlen (name)-2)!=-1) { strcat (path, ".d/"); mkdir (path, 0750); strcat (path, name); - symlink (file, path); + symlink (abspath (file), path); } else fprintf (stderr, "Cannot attach '%s'\n", file); } @@ -573,8 +627,6 @@ static void dmcfwd(const char *file, const char *addr, const char *msg, const ch int main(int argc, char **argv) { char file[128], line[128]; - struct dirent *de; - DIR *dir; int i; if (argc < 2) @@ -592,27 +644,11 @@ int main(int argc, char **argv) { switch (argv[1][1]) { case 'l': if (argc>2) { - snprintf (line, sizeof (line), "%s/box/%s/in/%s.eml", dmcdir, acc[0], argv[2]); - if (fexist (line)) { - snprintf (line, sizeof (line), "cat '%s/box/%s/in/%s.eml'", - dmcdir, acc[0], argv[2]); - system (line); // implement native cat + if (dmccat (argv[2])) break; - } snprintf (line, sizeof (line), "%s/box/%s", dmcdir, argv[2]); } else snprintf (line, sizeof (line), "%s/box/%s/in", dmcdir, acc[0]); - if ((dir = opendir (line))) { - while ((de = readdir (dir))) { - if (*de->d_name!='.') { - char *subj = gethdr (line, de->d_name, "Subject: "); - char *from = gethdr (line, de->d_name, "From: "); - printf ("%s:\t%s\n\t%s\n", de->d_name, subj, from); - free (from); - free (subj); - } - } - closedir (dir); - } + dmcls (line); break; case 'A': for (i=2; i<argc; i++) @@ -711,10 +747,10 @@ int main(int argc, char **argv) { } dmcstop (); break; - case 'r': // reply + case 'r': dmcfwd (dmcmailpath (argv[2]), argc>3?argv[3]:"", REPMSG, REPSUB); break; - case 'f': // forward + case 'f': dmcfwd (dmcmailpath (argv[2]), argc>3?argv[3]:"", FWDMSG, FWDSUB); break; default: