commit 98abdf81d2683dcda7b9b9fa3f8c58f061f88c26
Author: Tomas Hlavaty <tom@logand.com>
Date: Mon, 15 Nov 2010 21:57:47 +0100
Initial commit
Diffstat:
A | Makefile | | | 9 | +++++++++ |
A | cmd.c | | | 57 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | cmd.h | | | 14 | ++++++++++++++ |
A | io.c | | | 39 | +++++++++++++++++++++++++++++++++++++++ |
A | io.h | | | 9 | +++++++++ |
A | w3mail.c | | | 46 | ++++++++++++++++++++++++++++++++++++++++++++++ |
6 files changed, 174 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,9 @@
+all: w3mail
+
+CFLAGS=-g -Wall -std=c99 -pedantic -D_XOPEN_SOURCE=600
+
+w3mail: io.o cmd.o w3mail.o
+ $(CC) $(CFLAGS) -o w3mail io.o cmd.o w3mail.o
+
+clean:
+ rm -f *~ *.o w3mail
diff --git a/cmd.c b/cmd.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include "cmd.h"
+#include "io.h"
+
+extern void quit(int code, char *fmt, ...);
+extern const int BLEN;
+
+void wget(char *url, char *fname) {
+ int pid = fork();
+ if(pid < 0) quit(pid, "wget(): fork failed");
+ else if(pid == 0) execlp("wget", "wget", "-q", "-O", fname, "--", url, NULL);
+ else wait(NULL);
+}
+
+static void cb_md5sum(void *udata, FILE* in) {
+ char *sum = udata;
+ sum = fgets(sum, 33, in);
+}
+
+void md5sum(char *fname, char *sum) {
+ char cmd[BLEN];
+ snprintf(cmd, BLEN, "md5sum '%s'", fname);
+ in(sum, cb_md5sum, cmd);
+}
+
+static void echo(char *fname, FILE *out) {
+ FILE *in = fopen(fname, "r");
+ if(!in) quit(1, "echo(): cannot open input file '%s'", fname);
+ char buf[BLEN];
+ int n;
+ while(0 < (n = fread(buf, sizeof(char), BLEN, in)))
+ fwrite(buf, sizeof(char), n, out);
+ fclose(in);
+}
+
+#define pr(...) {fpr(out, __VA_ARGS__, NULL); fprintf(out, "\r\n");}
+
+void cb_sendmail(void *udata, FILE* out) {
+ struct sendmail *x = udata;
+ pr("From: ", x->from);
+ pr("To: ", x->to);
+ if(x->id) pr("Message-ID: ", x->id);
+ pr("Subject: ", x->subj);
+ pr("User-Agent: w3mail");
+ pr("MIME-Version: 1.0");
+ pr("Content-Type: text/html"); // ; charset=utf-8
+ pr("Content-Disposition: inline; filename=", x->fname);
+ pr("Content-Transfer-Encoding: 8bit");
+ pr("");
+ echo(x->fname, out);
+ pr("");
+ pr("");
+}
diff --git a/cmd.h b/cmd.h
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+void wget(char *url, char *fname);
+void md5sum(char *fname, char *sum);
+
+struct sendmail {
+ char *from;
+ char *to;
+ char *id;
+ char *subj;
+ char *fname; // TODO char *fname[]
+};
+
+void cb_sendmail(void *udata, FILE* out);
diff --git a/io.c b/io.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "io.h"
+
+extern void quit(int code, char *fmt, ...);
+
+void in(void *udata, in_cb cb, char *cmd) {
+ FILE *pipe = popen(cmd, "r");
+ if(!pipe) quit(1, "in(): cannot open pipe to '%s'", cmd);
+ cb(udata, pipe);
+ pclose(pipe);
+}
+
+void out(void *udata, out_cb cb, char *cmd) {
+ FILE *pipe = popen(cmd, "w");
+ if(!pipe) quit(1, "out(): cannot open pipe to '%s'", cmd);
+ cb(udata, pipe);
+ pclose(pipe);
+}
+
+void tmpf(void *udata, tmpf_cb cb, char *fname) {
+ int fd = mkstemp(fname);
+ if(fd == -1) quit(errno, "tmpf(): cannot create temporary file '%s'", fname);
+ close(fd);
+ cb(udata, fname);
+ unlink(fname);
+}
+
+void fpr(FILE *out, ...) {
+ va_list v;
+ va_start(v, out);
+ char *a;
+ while((a = va_arg(v, char *))) fprintf(out, "%s", a);
+ va_end(v);
+}
diff --git a/io.h b/io.h
@@ -0,0 +1,9 @@
+typedef void (*in_cb)(void *udata, FILE* in);
+typedef void (*out_cb)(void *udata, FILE* out);
+typedef void (*tmpf_cb)(void *udata, char *fname);
+
+void in(void *udata, in_cb cb, char *cmd);
+void out(void *udata, out_cb cb, char *cmd);
+void tmpf(void *udata, tmpf_cb cb, char *fname);
+
+void fpr(FILE *out, ...);
diff --git a/w3mail.c b/w3mail.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "cmd.h"
+#include "io.h"
+
+const int BLEN = 1024;
+
+void quit(int code, char *fmt, ...) { // TODO __func__
+ va_list v;
+ va_start(v, fmt);
+ char msg[BLEN];
+ vsnprintf(msg, BLEN, fmt, v);
+ perror(msg);
+ exit(code);
+ va_end(v);
+}
+
+struct w3mail {
+ char *cmd;
+ char *from;
+ char *to;
+ char *host;
+ char *url;
+};
+
+void cb_w3mail(void *udata, char *fname) {
+ struct w3mail *x = udata;
+ char sum[BLEN], id[BLEN], subj[BLEN];
+ wget(x->url, fname);
+ md5sum(fname, sum);
+ snprintf(id, BLEN, "<%s@%s>", sum, x->host);
+ snprintf(subj, BLEN, "[w3mail] %s", x->url);
+ struct sendmail y = {x->from, x->to, id, subj, fname};
+ out(&y, cb_sendmail, x->cmd);
+}
+
+int main(int argc, char *argv[]) {
+ if(argc != 6) quit(1, "usage: %s cmd from to host url", argv[0]);
+ char fname[BLEN];
+ snprintf(fname, BLEN, "/tmp/w3mail-XXXXXX");
+ struct w3mail x = {argv[1], argv[2], argv[3], argv[4], argv[5]};
+ tmpf(&x, cb_w3mail, fname);
+ return 0;
+}