taylor@limbo.Intuitive.Com (Dave Taylor) (06/07/90)
As a site that has a real domain name but UUCP only connectivity, I have been continually frustrated by the mismatch of the abilities of the Sendmail program and the needs of the UUX portion of UUCP. In a nutshell, to have "domain-ized" email come from my site, I need to have the message queued in UUCP with the following format: From <username> <date> remote from <hostname> From: <username>@<qualified.hostname> (<fullname>) Problem is, "sendmail" wants to have the 'username' in the first From_ line match the 'username@<qualified.hostname>' in the second. The bigger problem on top of that is that uux absolutely insists on either the "remote from host" format, or having a "hostname!" prefix on the address in the From_ line. The easy solution, of course, is to have "sendmail" output the common address as "hostname!user@qualified-hostname", but, frankly, I think that email addresses like "limbo!taylor@limbo.intuitive.com" look quite terrible! Instead, what I did as a Unix style hack was to teach "sendmail" to deliver UUCP mail to a different program instead of "uux"; the program attached below, called "uux.filter". The "sendmail.cf" file was hacked on a bit so that it now *doesn't* think that "uux" is a UUCP style mailer (e.g the "U" flag in the "F=" mailer definition) and so that it just uses domain style "user@host.domain" addresses for both the From: and From_ lines. So what ends up happening is that a typical message comes out of "sendmail" like: From taylor@limbo.intuitive.com <date> From: taylor@limbo.intuitive.com (Dave Taylor) Subject: hi and then "uux.filter" rewrites it as: From taylor <date> remote from limbo From: taylor@limbo.intuitive.com (Dave Taylor) Subject: hi and hands it to the real "uux" program. End result: "uux" and the entire "uucp" package is happy, *and* we end up with nice looking From: addresses without mixed mode, redundant hostname addresses. The modification to my "sendmail.cf" file is on the two mailer definition lines below - note the P= value and the F= flags... ############################################################ ### UUCP mailer ### ############################################################ Muucp, P=/usr/bin/uux.filter, F=DFMshu, S=13, R=23, A=uux - $h!rmail ($u) S13 R$+<@$+.UUX> $@$2!$1<@$H.UUX> host!user => my_host!host!user R$+<@$+> $@$1%$2<@$j> user@host => user%host@my_host R<@$+>:$+ $@<@$j>:@$1:$2 prepend @my_host to route R$+ $@$1<@$j> user => user@my_host S23 ############################################################ ### Dumb UUCP mailer ### ############################################################ Mdumbuucp, P=/usr/bin/uux.filter, F=DMshux, R=23, A=uux - $h!rmail ($u) As you can see, we simply "stick it in the middle". Enjoy! -- Dave Taylor taylor@limbo.intuitive.com -- Attachment: "uux.filter.c" /** uux.filter.c **/ /** A simple program that puts itself in front of the standard "uux" command to allow us to have non-UUCP style messages come from "sendmail" and end up, correctly formatted, in the UUCP outbound queue. Note that the "real" uux is still used; we just expect "sendmail" to call us instead. The fixing up involved in this program is simply to change the format of the "From " line to ensure that it ends with the suffix of "remote from HOSTNAME". (C) Copyright 1990, Dave Taylor, Intuitive Systems. Distribution of any nature allowed as long as this header is retained without modification. Compile with: "cc -O uux.filter.c -o uux.filter" and then fix your "sendmail.cf" UUCP mailer definition to know about it. **/ /** include the following if you're debugging your installation... #define DEBUGGING **/ #include <stdio.h> #include <errno.h> #include <ctype.h> #define REAL_UUX "/usr/bin/uux" #define TEMPFILE "/tmp/uux.fix.%d" /** the following should be changed to reflect your own site values! **/ #define HOSTNAME "limbo" #define TO_STRIP "@limbo.intuitive.com" /** compares in a case-independent way... **/ #define same_char(c,d) (c == d || c == isupper(d) ? tolower(d) : d || \ d == isupper(c) ? tolower(c) : c) extern int errno; main(argc, argv) int argc; char **argv; { FILE *pipe_to_uux; char uux_command[4096]; char buffer[256]; /** build up the command to the real uux program **/ argv++; strcpy(uux_command, REAL_UUX); while (--argc) { /* grab args.. */ strcat(uux_command, " '"); /* and quote */ strcat(uux_command, *argv++); /* them! */ strcat(uux_command, "'"); } /** now let's try to open a write-only pipe to "uux" **/ if ((pipe_to_uux = popen(uux_command, "w")) == NULL) { printf("uux.filter: failed trying to popen(%s) error=%d\n", uux_command, errno); exit(1); /* This will cause a sendmail bounce messsage */ } else { while (gets(buffer) != NULL) { if (strncmp(buffer, "From ", 5) == 0) { fix_buffer(buffer); fprintf(pipe_to_uux, "%s remote from %s\n", buffer, HOSTNAME); } else fprintf(pipe_to_uux, "%s\n", buffer); } pclose(pipe_to_uux); } #ifdef DEBUGGING printf("uux.filter: delivered message to '%s'\n", uux_command); #endif exit(0); } fix_buffer(buffer) char *buffer; { /** Given a buffer of the form "From user@host <DATE>" return it as "From user <DATE>" We do this by stripping out the @host field; but only iff it matches our "TO_STRIP" value as we go along. As soon as it fails, we'll bail! **/ char ourbuffer[256]; register int i, j = 0, k=1; int skip = 0; for (i = 0; buffer[i] != 0; i++) { if (buffer[i] == '@') skip = 1; if (buffer[i] == ' ' && skip) skip = 0; if (! skip) ourbuffer[j++] = buffer[i]; else if (! same_char(buffer[i], TO_STRIP[k])) { /* they don't match */ #ifdef DEBUGGING printf("uux.filter: fields '%s' and '%s' diverge at char %d/%d\n", buffer, TO_STRIP, i, k); #endif return; } } ourbuffer[j] = 0; strcpy(buffer, ourbuffer); } /** end of program listing **/