#include #include #include #include #include #include #include #include int wr = -1; int rd = -1; void do_write (int fd, char * buf, int len) { int done = 0; int ret; while (done < len) { ret = write (fd, buf+done, len - done); if (ret < 0) { if ((errno != EINTR) || (errno == EAGAIN)) { continue; } perror ("write"); fprintf (stderr, "Aborting\n"); exit (1); } done += ret; } } int readline (int fd, stralloc * sa) { int ret = 0; if (!sa) return 0; sa->len = 0; while (1) { char ch; int tmp; tmp = read (fd, &ch, 1); if (tmp == 0) break; if (tmp < 0) continue; if (!stralloc_readyplus (sa, 1)) return 0; sa->s[sa->len] = ch; sa->len++; if (ch == '\n') break; } ret = (sa->len > 0); while (sa->len && ((sa->s[sa->len-1] == '\r') || (sa->s[sa->len-1] == '\n'))) sa->len--; return ret; } void readreply (int expect); void terminate (stralloc * error) { static int in_terminate = 0; if (error) { fwrite (error->s, sizeof (char), error->len, stderr); fprintf (stderr, "\n"); } if (!in_terminate) { do_write (wr, "QUIT\r\n", 6); in_terminate = 1; readreply (2); } exit (1); } void temp_error (stralloc * error) { fprintf (stderr, "Temporary failure: "); terminate (error); } void fatal_error (stralloc * error) { fprintf (stderr, "Fatal error: "); terminate (error); } void do_quit (stralloc * error) { stralloc sa = {0}; do_write (wr, "QUIT\r\n", 6); readreply (2); stralloc_copys (&sa, "Server sent unexpected answer: "); stralloc_cat (&sa, error); fatal_error (&sa); } void readreply (int expect) { struct stralloc sa = {0}; int code; char ch; if (!readline (rd, &sa)) { stralloc_copys (&sa, "Unexpected end of file"); fatal_error (&sa); } if ((sscanf (sa.s, "%d%c", &code, &ch) != 2) || (code < 0) || (code > 999)) { stralloc_copys (&sa, "Badly formed reply from server"); fatal_error (&sa); } switch (sa.s[0]) { default: stralloc_copys (&sa, "Badly formed reply from server"); fatal_error (&sa); break; case '1': do_quit (&sa); break; case '2': if (expect != 2) do_quit (&sa); break; case '3': if (expect != 3) do_quit (&sa); break; case '4': temp_error (&sa); break; case '5': fatal_error (&sa); break; } } const char thishost[] = "elbereth.mathematik.uni-ulm.de"; const char domain[] = "mathematik.uni-ulm.de"; const char * buddies[] = { "ehrhardt@mathematik.uni-ulm.de", "Christian.Ehrhardt@mathematik.uni-ulm.de", /* Hier sollten alle Tutoriumsteilnehmer stehen. */ NULL }; int main () { int i, pid; char * user = getenv ("USER"); stralloc sa = {0}; int p1[2], p2[2]; if (!user) { fprintf (stderr, "Can't find out username\n"); exit (1); } if (pipe (p1) < 0) { perror ("pipe"); exit (1); } if (pipe (p2) < 0) { perror ("pipe"); exit (1); } pid = fork (); if (pid < 0) { perror ("fork"); exit (1); } if (pid == 0) { /* CHILD */ if (dup2 (p1[0], 0) < 0) { perror ("dup2"); exit (1); } close (p1[0]); close (p1[1]); if (dup2 (p2[1], 1) < 0) { perror ("dup2"); exit (1); } close (p2[0]); close (p2[1]); execlp ("nc", "nc", "theseus.mathematik.uni-ulm.de", "25", NULL); perror ("execlp"); exit (1); } /* PARENT */ close (p1[0]); close (p2[1]); wr = p1[1]; rd = p2[0]; /* Read greating. */ readreply (2); /* Send HELO */ if (!stralloc_copys (&sa, "HELO ") || !stralloc_cats (&sa, thishost) || !stralloc_cats (&sa, "\r\n")) { terminate (NULL); } do_write (wr, sa.s, sa.len); readreply (2); /* Send our Email-Adresse as Sender. */ if (!stralloc_copys (&sa, "MAIL From: ") || !stralloc_cats (&sa, user) || !stralloc_cats (&sa, "@") || !stralloc_cats (&sa, domain) || !stralloc_cats (&sa, "\r\n")) terminate (NULL); do_write (wr, sa.s, sa.len); readreply (2); for (i = 0; buddies[i]; i++) { if (!stralloc_copys (&sa, "RCPT To: ") || !stralloc_cats (&sa, buddies[i]) || !stralloc_cats (&sa, "\r\n")) terminate (NULL); do_write (wr, sa.s, sa.len); readreply (2); } do_write (wr, "DATA\r\n", 6); readreply (3); /* Header */ if (!stralloc_copys (&sa, "Subject: Wichtige Nachricht an die Tutoriumsgruppe\r\n") || !stralloc_cats (&sa, "From: ") || !stralloc_cats (&sa, user) || !stralloc_cats (&sa, "@") || !stralloc_cats (&sa, domain) || !stralloc_cats (&sa, "\r\n") || !stralloc_cats (&sa, "To: mein.tutorium@mathematik.uni-ulm.de\r\n\r\n")) terminate (NULL); do_write (wr, sa.s, sa.len); /* Text von der Standardeingabe */ while (readline (0, &sa)) { if (sa.s[0] == '.') do_write (wr, ".", 1); do_write (wr, sa.s, sa.len); do_write (wr, "\r\n", 2); } do_write (wr, ".\r\n", 3); readreply (2); do_write (wr, "QUIT\r\n", 6); readreply (2); close (wr); close (rd); wait (NULL); printf ("Mail sent\n"); return 0; }