w3mail

program to send a web page by email
git clone https://logand.com/git/w3mail.git/
Log | Files | Refs | README | LICENSE

commit 98abdf81d2683dcda7b9b9fa3f8c58f061f88c26
Author: Tomas Hlavaty <tom@logand.com>
Date:   Mon, 15 Nov 2010 21:57:47 +0100

Initial commit

Diffstat:
AMakefile | 9+++++++++
Acmd.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acmd.h | 14++++++++++++++
Aio.c | 39+++++++++++++++++++++++++++++++++++++++
Aio.h | 9+++++++++
Aw3mail.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; +}