Newsgroups: comp.sources.unix From: takahasi@isl.rdc.toshiba.co.jp (TAKAHASHI Toshinari) Subject: v28i157: mail-expand - sendmail wrapper to expand and check addresses, Part01/01 Message-id: <1.784075741.10218@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: takahasi@isl.rdc.toshiba.co.jp (TAKAHASHI Toshinari) Posting-Number: Volume 28, Issue 157 Archive-Name: mail-expand/part01 Mail-expand is a utility to interpret given mail address(es) and checks its justification according to the rewriting rules or aliasing mechanism of sendmail. Example: % mail-expand mail-expand@isl.rdc.toshiba.co.jp returns R> TAKAHASHI Toshinari See online manual and README for details. This utility was released on Mar. 17 1994 at fj.sources (Japan). The online manual written in English is released at this time of the day!! Enjoy! TAKAHASHI Toshinari Communication and Information Systems Research Labs. TOSHIBA R&D Center #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 09/24/1994 07:12 UTC by takahasi@air # Source directory /tmp # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 1629 -rw-r--r-- mail-expand/COPYRIGHT # 926 -rw-r--r-- mail-expand/README # 8344 -rw-r--r-- mail-expand/man/man1/mail-expand.1 # 20428 -rw-r--r-- mail-expand/src/mail-expand.c # 382 -rw-r--r-- mail-expand/src/makefile # 3113 -rw-r--r-- mail-expand/src/resolv.c # # ============= mail-expand/COPYRIGHT ============== if test ! -d 'mail-expand'; then echo 'x - creating directory mail-expand' mkdir 'mail-expand' fi if test -f 'mail-expand/COPYRIGHT' -a X"$1" != X"-c"; then echo 'x - skipping mail-expand/COPYRIGHT (File already exists)' else echo 'x - extracting mail-expand/COPYRIGHT (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mail-expand/COPYRIGHT' && ----------------------------------------------------------------------- Sendmail recipients expansion command (mail-expand) Copyright Notice ----------------------------------------------------------------------- X Sendmail recipients expansion command (mail-expand) Copyright (c) 1993 TOSHIBA Corporation All rights reserved X Permission to use, copy, and modify this software and its documents for research purposes only is hereby granted without any fee, subject to the following restrictions: X Mail-expand must not be distributed with any product, nor should any program with mail-expand built-in be distributed, without written permission of TOSHIBA Corporation. X The copyright notice and this permission notice must appear in all copies or modified versions of this software. X TOSHIBA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL TOSHIBA CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. X Please notify all modifications and bugs to the following address: X X Research Laboratory I X Communication and Information Systems Research Laboratories X TOSHIBA R & D Center X 1 Komukai-Toshiba-cho, X Saiwai-ku, Kawasaki 210 X JAPAN X E-mail: mail-expand@isl.rdc.toshiba.co.jp. X TOSHIBA Corporation has rights to use, copy, modify and distribute all reported modifications for any purpose. X SHAR_EOF chmod 0644 mail-expand/COPYRIGHT || echo 'restore of mail-expand/COPYRIGHT failed' Wc_c="`wc -c < 'mail-expand/COPYRIGHT'`" test 1629 -eq "$Wc_c" || echo 'mail-expand/COPYRIGHT: original size 1629, current size' "$Wc_c" fi # ============= mail-expand/README ============== if test -f 'mail-expand/README' -a X"$1" != X"-c"; then echo 'x - skipping mail-expand/README (File already exists)' else echo 'x - extracting mail-expand/README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mail-expand/README' && ------------------------------------------------------------------------------- Sendmail recipients expansion command (mail-expand) Introduction ------------------------------------------------------------------------------- X COPYRIGHT NOTICE ---------------- See the file "COPYRIGHT" in the top directory of the release. X X WHAT IS mail-expand ? ---------------------- Mail-expand is a mail utility program based on sendmail-R8 created at TOSHIBA Research and Development Center. X INSTALL ------- Run "make mail-expand" at the directory named "src". It has been tested on SunOS 4.1.[123] and SunOS 5.[13]. X Set your local domain name to the macro 'DOMAIN' in the makefile if you prefer a simple username rather than username@LocalDomainName. X HOW TO USE mail-expand ---------------------- Use as follows: X X % mail-expand recipients X Please install the manual page placed in the directory "man" for more detailed information. SHAR_EOF chmod 0644 mail-expand/README || echo 'restore of mail-expand/README failed' Wc_c="`wc -c < 'mail-expand/README'`" test 926 -eq "$Wc_c" || echo 'mail-expand/README: original size 926, current size' "$Wc_c" fi # ============= mail-expand/man/man1/mail-expand.1 ============== if test ! -d 'mail-expand/man'; then echo 'x - creating directory mail-expand/man' mkdir 'mail-expand/man' fi if test ! -d 'mail-expand/man/man1'; then echo 'x - creating directory mail-expand/man/man1' mkdir 'mail-expand/man/man1' fi if test -f 'mail-expand/man/man1/mail-expand.1' -a X"$1" != X"-c"; then echo 'x - skipping mail-expand/man/man1/mail-expand.1 (File already exists)' else echo 'x - extracting mail-expand/man/man1/mail-expand.1 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mail-expand/man/man1/mail-expand.1' && .\" Sendmail recipients expansion command (mail-expand) .\" Copyright (c) 1993 TOSHIBA Corporation .\" All rights reserved .\" .\" Permission to use, copy, and modify this software and its documents .\" for research purpose only is hereby granted without any fee, subject .\" to the following restrictions: .\" It is not permitted to distribute any products made with mail-expand, .\" or any programs made with mail-expand are built in without any written .\" permissions of TOSHIBA Corporation. .\" .\" The copyright notice and this permission notice must appear in all .\" copies or modified versons of this software. .\" .\" TOSHIBA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS .\" SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND .\" FITNESS, IN NO EVENT SHALL TOSHIBA CORPORATION BE LIABLE FOR ANY .\" SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER .\" RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF .\" CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN .\" CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" We would like to request notification of all modifications and bugs to .\" the following address: .\" .\" Research Laboratory I .\" Communication and Information Systems Research Laboratories .\" TOSHIBA R & D Center .\" 1, Komukai-Toshiba-cho, .\" Saiwai-ku, Kawasaki 210 .\" JAPAN .\" E-mail: mail-expand@isl.rdc.toshiba.co.jp. .\" .\" TOSHIBA Corporation has rights to use, copy, modify and distribute all .\" reported modifications for any purpose. .\" .\" @(#)mail-expand.1 1.6 (TOSHIBA R&D) 94/09/17 .\" .TH MAIL-EXPAND 1 "12 October 1992" .SH NAME mail-expand \- check mail recipients over the internet .SH SYNOPSIS .B mail-expand [ .B \-efhlnsVv ] .I recipient ... .SH DESCRIPTION .B Mail-expand interprets given mail address(es) and checks its justification according to the rewriting rules or aliasing mechanism of .BR sendmail (1). .LP First, .B mail-expand calls local sendmail and checks the justification of the mail address, translates it according to the rules, and gets the mailer name, and destination host name. After this, if it uses SMTP as a mailer, it connects to the destination host by SMTP and expands the mail address with aliases, .forward, etc. using the EXPN command. If SMTP is not used, every check is done except getting GCOS information about local users. .LP If SMTP connection fails, the expanding procedure on the remote host is omitted and the local translation is used as the final result. .LP The `R> ' prompt means `remote' i.e. both the local translation and the remote expansion have succeeded. The `L> ' prompt means `local' i.e. the LOCAL mailer on the local host is called. The `P> ' prompt means `program' i.e. the PROG mailer on the local host is called. Usually, you can get one of the three prompt for every recipient, but if you can not connect to the remote host via SMTP, which means remote sendmail is down or network is unreachable, or your site uses UUCP transfer for mail, you get the `D> ' prompt which means `down'. In this case, you have to pay attention to the fact that the result you obtained has never been tested on the remote host, and so it may cause error when you actually send mail. .LP If you define your local domain name to the macro `DOMAIN' when compiling, the local domain name set on the mail address is not printed. This function is only for user-readability, and the local domain name mentioned here has no relationship to either the NIS domain name or the name server definition. .LP .SH OPTIONS .TP .B \-e Enumerate only the mail addresses as the result. .LP .TP .B \-f Warning message about failure to connect to the remote host via SMTP is disabled. .TP .B \-h Print header line including the name of the destination remote host and its mailer name. .TP .B \-l Translated by sendmail on the local host only. Expansion on a remote host is omitted. This option may be used if you want quick execution rather than an exact result. .TP .B \-n Don't remove local domain name from result. This option has meaning only if the local domain name is defined when compiling. .TP .B \-s Silent mode. No result address is printed except for error messages and 0 is returned if and only if no error is detected, otherwise 1 is returned. .LP .RS The \-s option invalidates neither the \-h nor the \-v option. For example, You can set both the \-s and \-h options when you are interested in the destination host rather than each recipient. .RE .TP .B \-v Verbose mode. The sequence communicating with local sendmail or remote SMTP connections can be seen. Sending characters are shown with `% ' prompts, and receiving characters are shown with `==>' prompts. For debug purposes, it is best to use the \-V option, described later, rather than this option. .TP .B \-V Similar to the \-v option. Executes all connections sequentially. .B Mail-expand usually opens multiple SMTP connections simultaneously and uses three paths for each connection set. This is because .B mail-expand can finish its execution in time even when some connections are very late to respond. When you set this option, all SMTP connections are opened and closed one after another, so debug messages can be read easily. .SH FILES .PD 0 .B /etc/aliases .TP .B /etc/sendmail.cf .TP .B /usr/lib/sendmail .TP .B /etc/resolv.conf .PD .SH "SEE ALSO" .LP .BR sendmail (8), .BR aliases (5), .BR newaliases (8), .BR mail (1), .BR csh (1), .BR telnet (1c), .BR resolver (3), .BR nslookup (8), .BR named (8C) .SH NOTES .B Mail-expand applies rules defined by .B sendmail(1) to all translations and expansions, never taking into account the specifications of the mail handling application. For example, .B mail-expand never refers to .B .mailrc in your home directory. .LP It is the policy of .B mail-expand to emulate the management of .B sendmail(1) exactly. Therefore you can use .B mail-expand to check the mail system itself. .LP When a delivery error is detected, .B mail-expand is terminated at that point, and everyone else to be printed is ignored. .LP One useful statement in .B csh(1) is .RS % mail-expand recipient ... .RE checks the justification of all recipients and .RS % mail !* .RE actually sends mail. .LP .B Mail-expand refers to an MX field from resolver (name server) with the name which is obtained from the local machine's sendmail. .B Mail-expand makes SMTP connection only to the host which has the minimum preference value, and ignores other MX hosts, if they exist. This means that .B mail-expand would like to connect to the host which has the most useful information about the recipients. Accordingly, .B mail-expand sometimes connects to a different host from that to which .B sendmail connects. .LP .B Mail-expand refers to an A field instead of an undefined MX field. .B Mail-expand refers to an A field from the beginning if .B sendmail specifies to use an A field in the configuration file. .LP When the recipient to be delivered to is not a local user on the remote host, you cannot get detailed information, such as GCOS, about the recipient. This is the typical case for a mailing list on a remote host. In this case, you can expand results repeatedly as follows .RS % mail-expand `mail-expand -e mailing-list-name` .RE and you may get more useful information about the members. But this is not the same procedure by which .B sendmail expands mail addresses and delivers them, and so .B mail-expand cannot guarantee the result, although it usually gives you some useful information. .LP .B Mail-expand is designed for sendmail-R8. If the sendmail on your host is old, expansion on remote hosts is not tried. If the sendmail on the remote host is version-4 or earlier, you can get nothing more than the string "OK" as the result of the EXPN command. .LP .B Mail-expand evaluates the mailer which .B sendmail uses from the mailer strings `smtp', `relay', `local', `prog' and `uucp'. Of these `smtp' and `relay' mean SMTP, `local' means LOCAL, `prog' means PROG, and `uucp' means UUCP. .B Mail-expand cannot handle other names or the same names with other meanings. .SH DIAGNOSTICS .B Mail-expand returns a zero (true) exit status if no error is detected concerning the specified recipients; otherwise 1 (false) exit status is returned. SHAR_EOF chmod 0644 mail-expand/man/man1/mail-expand.1 || echo 'restore of mail-expand/man/man1/mail-expand.1 failed' Wc_c="`wc -c < 'mail-expand/man/man1/mail-expand.1'`" test 8344 -eq "$Wc_c" || echo 'mail-expand/man/man1/mail-expand.1: original size 8344, current size' "$Wc_c" fi # ============= mail-expand/src/mail-expand.c ============== if test ! -d 'mail-expand/src'; then echo 'x - creating directory mail-expand/src' mkdir 'mail-expand/src' fi if test -f 'mail-expand/src/mail-expand.c' -a X"$1" != X"-c"; then echo 'x - skipping mail-expand/src/mail-expand.c (File already exists)' else echo 'x - extracting mail-expand/src/mail-expand.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mail-expand/src/mail-expand.c' && /* ** ** @(#)mail-expand.c 9.22 ** ** Interprets given mail address(es) and checks its ** justification according to the rewriting rules or ** aliasing mechanim of sendmail. ** ** Usage: %s [-efhlnsVv] recipient ... ** ** Options: ** -e Enumerate only the mail addresses as the result ** -f Warning about failure to connect is disabled ** -h Print header line (remote host name etc.) ** -l Translated on the local host only ** -n Don't remove local domain name from result. ** -s silent mode. ** -v verbose mode. ** -V verbose mode for sequential debugging. ** ** Prompts: ** R> Both the local and remote expansion have succeeded. ** P> PROG mailer on the local host is called. ** L> LOCAL mailer on the local host is called. ** D> SMTP connection failed or UUCP transfer. ** ==> receiving characters in verbose mode. ** % sending characters in verbose mode. ** ** 94/09/17 19:23:36 ** ** by takahasi@isl.rdc.toshiba.co.jp (TAKAHASHI Toshinari) ** */ X /* ** Sendmail recipients expansion command (mail-expand) ** Copyright (c) 1993 TOSHIBA Corporation ** All rights reserved ** ** TOSHIBA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS ** SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND ** FITNESS, IN NO EVENT SHALL TOSHIBA CORPORATION BE LIABLE FOR ANY ** SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ** RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ** CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ X #include #include X #define SMTPNO 25 /* SMTP port number */ #define HOSTLEN 64 /* Maximum length of destination host */ #define ADDRLEN 64 /* Maximum length of recipient (excludeing GCOS) */ #define RECIPIENTS 512 /* Maximum number of recipients */ #define MAX_SMTP 20 /* Maximum number of simultaneous smtp connections */ #define SMTPLEN 244 /* Maximum length of SMTP command X (Thanks to nitta@ns.c.u-tokyo.ac.jp) */ X #define SENDMAIL "/usr/lib/sendmail" #ifdef DEBUG #define IF_DEBUG(x) x #else DEBUG #define IF_DEBUG(x) ; #endif DEBUG X #define STDIN 0 #define STDOUT 1 #define STDERR 2 #define READ 0 /* fildes[0] */ #define WRITE 1 /* fildes[1] */ #define TRUE 1 #define FALSE 0 X #define TMPSIZE 8192 /* Maximum length of all arguments */ #define MAX_USERS 64 /* Maximum recipients on the same destination */ X #ifndef lint char copyright [] = "Copyright (c) 1993 Toshiba Corporation. (takahasi@isl.rdc.toshiba.co.jp)"; static char sccsid [] = "@(#)mail-expand.c 9.22 9/17/94 19:23:36"; #endif lint X /* resolv.c */ #include extern u_char *get_MX(), *get_A(); /* network */ #include #include #include #include X #ifdef Solaris # define bcopy(s, d, l) memmove((d), (s), (l)) #endif X int silent = FALSE; /* "-s" option */ int enumerate = FALSE; /* "-e" option */ int notdelete = FALSE; /* "-n" option */ X enum MAILER { SMTP, UUCP, LOCAL, PROG }; enum STATE { YET, DONE }; X char *mailer_name(tag) X enum MAILER tag; X { return (tag==SMTP ? "SMTP" : X (tag==UUCP ? "UUCP" : X (tag == LOCAL ? "LOCAL" : X (tag == PROG ? "PROG" : "UNKNOWN")))); } X struct recipient X { u_char hostname[HOSTLEN]; /* destination host name */ X char address[ADDRLEN]; /* e-mail address */ X enum MAILER mailer; /* SMTP, UUCP, LOCAL PROG */ X enum STATE checked; /* Where am I? */ X }; X void err(str) char *str; { perror(str); exit(1); } X /* ** doprint(tag, address) ** Read address info and set < > if necessary, ** delete bogus domain name. ** *address will be broken. */ void doprint(tag, address) X char tag; /* 'L' or 'R' */ X char *address; X #define UNPARSABLE(str) \ X fprintf(stderr, "SYSERR: unparsable format \"%s\"\n", str); exit(1); X X { char *s, *start, *end; X static int printed = FALSE; /* printed more than 0 */ X start = strchr(address, '<'); X end = strchr(address, '>'); X if ((start != NULL) && (end != NULL)) /* expectant case */ X { if (start + 1 >= end) X { UNPARSABLE(address); } X } X else if ((start != NULL) || (end != NULL)) /* unbalanced <> */ X { UNPARSABLE(address); } X else /* UUCP? */ X { bcopy(address, address+1, strlen(address)+1); /* with last NULL */ X address[0] = '<'; X strcat(address, ">"); X start = address; X end = address + strlen(address) -1; X } X X /* start...end: */ X #ifdef DOMAIN X /* remove my domain name */ X X if (notdelete == FALSE) { /* '-E' is not specified */ X if ((strchr(start, '%') == NULL) && (strchr(start, '!') == NULL) && X ((s = strchr(start, '@')) != NULL) && (s + strlen(DOMAIN) == end) && X (strncmp(s, DOMAIN, strlen(DOMAIN)) == 0)) X { bcopy(end, s, strlen(end)+1); /* with last NULL */ X end = s; X } X } #endif DOMAIN X X if(silent == FALSE) X { if (enumerate == FALSE) X { printf("%c> %s\n", tag, address); } X else X { *end = '\0'; X if (printed != FALSE) printf(", "); /* excepting the first time */ X printf("%s", start+1); X } X } X printed = TRUE; X } X char *real_name(username) X char *username; X { struct passwd *pw; X static char buf[256]; X char *s=&buf[0], *s2; X X if ((pw = getpwnam(username)) == NULL) { fprintf(stderr, "%s\n", username);perror("getpwnam"); exit(1); } X if ((s2 = strchr(pw->pw_gecos, ',')) != NULL) *s2 = '\0'; X sprintf(s, "%s <%s>", pw->pw_gecos, username); X return s; X } X void chop(str) X char *str; X { char *s = str; X if (*s != '\0') X { s += (strlen(s) -1); X while((s>=str) && ((*s == '\n') || (*s == '\r'))) X { *s-- = '\0'; } X } X } X void dupopt(opt1, opt2) X char opt1, opt2; X { fprintf(stderr,"Can't specify both '%c' and '%c'\n", opt1, opt2); exit(1);} X main(argc, argv) X int argc; X char *argv[]; X { X int i,j,index; X int verbose = FALSE, /* "-v" or "-V" option */ X header = FALSE, /* "-h" option */ X local = FALSE, /* "-l" option */ X force = FALSE, /* "-f" option */ X sequential = FALSE; /* "-V" option */ X char tmp[TMPSIZE]; /* read buffer and temporal string */ X char *s, *s2; X u_char *us; X int fildes[2]; X FILE *read_fp; X struct recipient recipients[RECIPIENTS]; /* result on the local host */ X int No_of_recipients = 0; /* number of recipients[] */ X int error; X int max_smtp; /* Maxmum number of simultaneous smtp connections */ X enum MAILER mailer[MAX_SMTP]; X u_char hostname[MAX_SMTP][HOSTLEN]; X u_char usernames[MAX_SMTP][MAX_USERS][ADDRLEN]; X int users[MAX_SMTP]; X int expns[MAX_SMTP]; /* Number of typed EXPN command */ X FILE *smtp_read[MAX_SMTP], *smtp_write[MAX_SMTP]; X int hosts, hosts_e; X #define UNKNOWN_FORMAT(str) \ X { fprintf(stderr, "%s: SYSERR: unknown format \"%s\"\n", argv[0], str); \ X exit(1); \ X } X X /* check arguments */ X X if (argc <= 1) X { fprintf(stderr, "Usage: %s [-efhlnsVv] recipient ...\n", argv[0]); X exit(1); } X i = 1; /* index of the first name */ X while ((i < argc) && (argv[i][0] == '-')) X { for (j=1; j0; i++) X { if ((j += strlen(argv[i])) >= TMPSIZE-2) X { fprintf(stderr, "Argument too long (Max %d chars)\n", TMPSIZE); X exit(1); X } X strcat(s, argv[i]); X s2 = &s[strlen(s)-1]; X while ((s2 >= s) && (*s2 == ',')) s2--; /* delete bogus ',' */ X if (s2 >= s) X { *++s2 = ','; *++s2 = '\0'; } /* and set one ',' again */ X else X { *++s2 = '\0'; } X s = s2; X } X if (tmp[0] == '\0') X { exit(0); } /* no recipient given: finish successful */ X else X { s[strlen(s)-1] = '\0'; }/* delete last ',' */ X X /* call "sendmail -bv $recipients" on local host */ X X if (pipe(fildes) < 0) { err("pipe"); } X X if ( (i = vfork()) == 0 ) X { if ((dup2(fildes[WRITE], STDOUT) < 0)) { err("dup2"); } X (void)close( fildes[READ] ); /* fildes is used only for write */ X (void)execl( SENDMAIL, "sendmail", "-bv", tmp, (char *)0 ); X fprintf(stderr, "%s boot failed\n", SENDMAIL); X exit(1); X } X else if (i < 0) X { err("vfork"); } X (void)close( fildes[WRITE] ); /* fildes is used only for read */ X if (verbose == TRUE) X { printf("\n%% execl(%s, sendmail, -bv, \"%s\", 0)\n", SENDMAIL, tmp); } X if ((read_fp = fdopen(fildes[READ], "r")) == NULL) { err("fdopen"); } X X error = FALSE; /* error is detected on the address */ X while(fgets(tmp, TMPSIZE, read_fp) != NULL) X { X /* read the expanded result */ X chop(tmp); X if (verbose == TRUE) { printf("==> \"%s\"\n", tmp); } X X /* check errors */ X if ((s = strstr(tmp, "... deliverable: ")) == NULL) X { if ((s = strstr(tmp, "... deliverable")) != NULL) X { *s = '\0'; /* maybe old-sendmail */ X if(silent == FALSE) printf("D> %s\n", tmp); X } X else X { fprintf(stderr, "%s\n", tmp); X error = TRUE; X } X continue; X } X s += strlen("... deliverable: "); X X /* $name... deliverable: mailer $mailer, host $host, user $addr */ X /* $mailer: smtp, relay, local, prog, uucp etc. */ X /* $host: hostname, [hostname], "" */ X X /* set on recipients[] */ X X recipients[No_of_recipients].checked = YET; X if ((s2 = strstr(s, "mailer local,")) != NULL) X { recipients[No_of_recipients].mailer = LOCAL; X strcpy(recipients[No_of_recipients].hostname, "localhost"); X if ((s2 = strstr(s2, ", user ")) == NULL) UNKNOWN_FORMAT(tmp); X } X else if ((s2 = strstr(s, "mailer prog,")) != NULL) X { recipients[No_of_recipients].mailer = PROG; X strcpy(recipients[No_of_recipients].hostname, "localhost"); X if ((s2 = strstr(s2, ", user ")) == NULL) UNKNOWN_FORMAT(tmp); X } X else X { if ((s2 = strstr(s, "mailer uucp,")) != NULL) X { recipients[No_of_recipients].mailer = UUCP; } X else if (((s2 = strstr(s, "mailer relay,")) != NULL) || X ((s2 = strstr(s, "mailer smtp,")) != NULL)) X { recipients[No_of_recipients].mailer = SMTP; } X else X { if ((s2 = strstr(s, "mailer ")) != NULL) X { if ((s = strchr(s2, ',')) != NULL) { *s = '\0'; } X fprintf(stderr, "%s: SYSERR: unknown mailer %s\n", X argv[0], s2+strlen("mailer ")); X exit(1); X } X else X { UNKNOWN_FORMAT(tmp); } X } X if ((s = strstr(s2, " host ")) == NULL) UNKNOWN_FORMAT(tmp); X s += strlen(" host "); /* s -> hostname or ',' */ X if (*s == ',') UNKNOWN_FORMAT(tmp); X if ((s2 = strstr(s, ", user ")) == NULL) UNKNOWN_FORMAT(tmp); X *s2 = '\0'; /* s := hostname */ X if (*s == '[') X { s++; *(s2-1)= '\0'; } /* delete [ ] */ X else if (recipients[No_of_recipients].mailer == SMTP) X { char *s0 = s; X s = (char *)get_MX(s0); /* type nameserver by q=MX */ X if (verbose == TRUE) X { fprintf(stderr, "type_MX(\"%s\") ==> \"%s\".\n", s0, s); } X if (*s == '\0') X { if (verbose == TRUE) X { fprintf(stderr, X "Can't find MX. use \"%s\" as destination.\n", s0); X } X s = s0; X } X } X strcpy(recipients[No_of_recipients].hostname, s); X } X s2 += strlen(", user "); /* s2 := user */ X strcpy(recipients[No_of_recipients].address, s2); X IF_DEBUG(printf("mailer:%s host:%s address:%s\n", X mailer_name(recipients[No_of_recipients].mailer), X recipients[No_of_recipients].hostname, X recipients[No_of_recipients].address);) X if (++No_of_recipients == RECIPIENTS) X { fprintf(stderr, "Too many recipients (max %d)\n", RECIPIENTS); X exit(1); X } X } X (void)fclose(read_fp); X if (error == TRUE) { exit(1); } X #ifdef SORT X /* sort by mailer and hostname */ X { int cmr; X enum MAILER mailer; X u_char hostname[HOSTLEN]; X char address[ADDRLEN]; X X for(i=0; i 0) || ((cmr == 0) && (mailer > recipients[j].mailer))) X { recipients[i].mailer = recipients[j].mailer; X recipients[j].mailer = mailer; X strcpy(hostname, recipients[i].hostname); X strcpy(recipients[i].hostname, recipients[j].hostname); X strcpy(recipients[j].hostname, hostname); X strcpy(address, recipients[i].address); X strcpy(recipients[i].address, recipients[j].address); X strcpy(recipients[j].address, address); X } X } X } #endif SORT X X /* Evaluate MAX_SMTP hosts at most, and loop back to "loopstart" X while there are other hosts. X Caution: UUCP and PROG are included to this number also, and X so the actucal number to be treated is less than it. */ X X max_smtp = (sequential == TRUE) ? 1 : MAX_SMTP; loopstart: X /* X STEP 1 X X open smtp for SMTP mailer X and set NULL to smtp_read for LOCAL, UUCP and PROG mailer X */ X hosts=0; X for(index=0; index \"%d.%d.%d.%d\".\n", X hostname[hosts], *us, *(us+1), *(us+2), *(us+3)); } X GETLONG(i, us); X } X sin.sin_addr.s_addr = i; X sin.sin_family = AF_INET; X sin.sin_port = htons(SMTPNO); X if (verbose == TRUE) X { fprintf(stderr, "connecting to host %s, port %d\n", X hostname[hosts], SMTPNO); } X error = FALSE; X if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) X { if (force == FALSE) perror("socket"); error = TRUE; } X else if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) X { if (force == FALSE) perror("connect"); error = TRUE; } X else if (((smtp_read[hosts] = fdopen(dup(sock), "r")) == NULL) || X ((smtp_write[hosts] = fdopen(sock, "w")) == NULL)) X { err("fdopen"); } X if (error == TRUE) X { if (force == FALSE) X { fprintf(stderr,"Connection failed to %s\n",hostname[hosts]);} X smtp_read[hosts] = (FILE *)0; X } X } X hosts++; X if (hosts == max_smtp) break; X } X hosts_e = hosts; /* Number of hosts to be treated this time */ X X /* X STEP 2 X X type EXPN command for SMTP mailer only X */ X X for(hosts=0; hosts \"%s\"\n", tmp); } X } /* skip connection message */ X while((tmp[3] != ' ') && /* "220 ..." */ X (strstr(tmp, " Connection refused") == NULL) && X (strstr(tmp, " unknown host") == NULL)); X if (tmp[3] == ' ') /* smtp connection succeeded */ X { char write_buf[SMTPLEN]; X char *w_b = (char *)&write_buf[0]; X X /* "HELO" to disable "Opneedexpnhelo" */ X if (verbose == TRUE) X { printf("%% helo\n", w_b); } X fprintf(smtp_write[hosts], "helo\r\n"); X X /* type EXPN more than 0 times */ X expns[hosts] = 0; X *w_b = '\0'; X for(i=0; i= SMTPLEN - ADDRLEN) X { write_buf[strlen(w_b)-1] = '\0'; /* delete last ',' */ X if (verbose == TRUE) X { printf("%% expn %s\n", w_b); } X fprintf(smtp_write[hosts], "expn %s\r\n", w_b); X expns[hosts]++; X (void)fflush(smtp_write[hosts]); X *w_b = '\0'; X } X strcat(w_b, (char *)&usernames[hosts][i][0]); X strcat(w_b, ","); X } X if (*w_b != '\0') X { write_buf[strlen(w_b)-1] = '\0'; /* delete last ',' */ X if (verbose == TRUE) X { printf("%% expn %s\n", w_b); } X fprintf(smtp_write[hosts], "expn %s\r\n", w_b); X expns[hosts]++; X (void)fflush(smtp_write[hosts]); X } X } X else /* smtp connection failed */ X { if (force == FALSE) X { if (strstr(tmp, " Connection refused") != NULL) X { fprintf(stderr, X "Connection refused by %s\n", hostname[hosts]); } X else X { fprintf(stderr, "Unknown host %s\n", hostname[hosts]); } X } X (void)fclose(smtp_read[hosts]); X (void)fclose(smtp_write[hosts]); X smtp_read[hosts] = (FILE *)0; X /* Abandon to EXPN and use current usernames[hosts] as the X result. This is similar to the case "-l" is specified. */ X } X } X X /* X STEP 3 X X read result from network and print it X */ X X for(hosts=0; hosts %s\n", usernames[hosts][i]); } X else if (mailer[hosts] == LOCAL) X { doprint('L', real_name(usernames[hosts][i])); } X else X { doprint('D', usernames[hosts][i]); } X /* UUCP or SMTP(failed or -l opt) */ X } X } X continue; X } X for(i=0; i \"%s\"\n", tmp); } X /* read results from "EXPN" */ X do { if (fgets(tmp, 1000, smtp_read[hosts]) == NULL) X { fprintf(stderr, "Unexpected EOF\n"); exit(1); } X chop(tmp); X if (verbose == TRUE) X { fprintf(stderr, "==> \"%s\"\n", tmp); } X if (strncmp(tmp, "250", 3) == 0) X { doprint('R', &tmp[4]); } /* TAKA */ X else if (strncmp(tmp, "502", 3) == 0) /* Opnoexpn */ X { if (force == FALSE) X { fprintf(stderr, "%s: %s\n", hostname[hosts], &tmp[4]); } X if (silent==FALSE) X { for (i=0; i %s\n", tmp); X } X } X (void)fclose(smtp_read[hosts]); X (void)fclose(smtp_write[hosts]); X } X for(index=0; index 'mail-expand/src/makefile' && # @(#)makefile 1.5 94/03/17 19:04:08 # OBJ = mail-expand.o resolv.o X # for SunOS4.1.x CC = cc -O LIBS = -lresolv X # for SunOS5.x #CC = gcc -O -DSolaris #LIBS = -lresolv -lsocket X mail-expand: $(OBJ) X $(CC) -s $(OBJ) -o $@ $(LIBS) X mail-expand.o: mail-expand.c X $(CC) -c mail-expand.c \ X -DDOMAIN=\"@mailhost.isl.rdc.toshiba.co.jp\" X clean: X /bin/rm -f $(OBJ) mail-expand resolvtest SHAR_EOF chmod 0644 mail-expand/src/makefile || echo 'restore of mail-expand/src/makefile failed' Wc_c="`wc -c < 'mail-expand/src/makefile'`" test 382 -eq "$Wc_c" || echo 'mail-expand/src/makefile: original size 382, current size' "$Wc_c" fi # ============= mail-expand/src/resolv.c ============== if test -f 'mail-expand/src/resolv.c' -a X"$1" != X"-c"; then echo 'x - skipping mail-expand/src/resolv.c (File already exists)' else echo 'x - extracting mail-expand/src/resolv.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mail-expand/src/resolv.c' && /* ** @(#)resolv.c 1.5 ** ** mail-expand sub functions ** ** Sendmail recipients expansion command (mail-expand) ** Copyright (c) 1993 TOSHIBA Corporation ** All rights reserved ** ** TOSHIBA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS ** SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND ** FITNESS, IN NO EVENT SHALL TOSHIBA CORPORATION BE LIABLE FOR ANY ** SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ** RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF ** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN ** CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ X #include #include #include X #define MAXINT ~(1 << (sizeof(int) * 8 - 1)) #define SKIP(p, n) p += n X #define IF_DEBUG(x) X #ifndef lint static char sccsid [] = "@(#)resolv.c 1.5 9/17/94 20:00:17"; #endif lint X /* ** resolv_lookup(host, querytype) ** ** querytype == MX ** return the entry with minimum preference ** querytype == A ** return the pointer to the inet addr ** return NULL if the entry could not be found. */ u_char *resolv_lookup(host, querytype) X char *host; X int querytype; { X u_char *current, *tail; X int pref, k, n; X int min_pref = MAXINT; /* minimum preference value */ X u_char answer[PACKETSZ], exp_dn[PACKETSZ], result[PACKETSZ]; #define anslen sizeof(answer) #define length sizeof(exp_dn) X X n = res_search(host, C_IN, querytype, answer, anslen); X if (n == -1) { result[0] = '\0'; return((u_char *)result); } X X current = &answer[sizeof(HEADER)]; X tail = &answer[n]; X for (k = ntohs(((HEADER *)answer)->qdcount); k--; current += n + QFIXEDSZ) X if ((n = dn_skipname(current, tail)) < 0) { return(NULL); } X X k = ntohs(((HEADER *)answer)->ancount); X while (--k >= 0 && current < tail) X { if ((n = dn_expand(answer, tail, current, exp_dn, length)) < 0) break; X SKIP(current, n); X GETSHORT(k, current); X SKIP(current, sizeof(u_short) + sizeof(u_long)); X GETSHORT(n, current); X if (k != querytype) { SKIP(current, n); continue; } X if (querytype == T_A) return((u_char *)current); /* return IP-address */ X GETSHORT(pref, current); X if ((n = dn_expand(answer, tail, current, exp_dn, length)) < 0) break; X IF_DEBUG(printf("preference: %d domain: %s\n", pref, exp_dn)); X if (pref < min_pref) X { strcpy(result, exp_dn); X min_pref = pref; X } X SKIP(current, n); X } X if (min_pref >= 0) X { return((u_char *)result); } X else X { return(NULL); } } X /* ** get_MX(addr) ** ** refers MX field and return the entry with minimum preference. ** Last resutlt is cached for later use. */ u_char *get_MX(addr) X char *addr; X { static char last_arg[64] = ""; X static char last_result[64]; X if (strcmp(last_arg, addr) != 0) X { strcpy(last_arg, addr); X strcpy(last_result, resolv_lookup(addr, T_MX)); /* set new result */ X } X return((u_char *)last_result); X } X /* ** get_A(addr) ** refers A field and returns inet addr */ u_char *get_A(addr) X char *addr; X { return(resolv_lookup(addr, T_A)); } SHAR_EOF chmod 0644 mail-expand/src/resolv.c || echo 'restore of mail-expand/src/resolv.c failed' Wc_c="`wc -c < 'mail-expand/src/resolv.c'`" test 3113 -eq "$Wc_c" || echo 'mail-expand/src/resolv.c: original size 3113, current size' "$Wc_c" fi exit 0