home *** CD-ROM | disk | FTP | other *** search
- From: barnett@grymoire.crd.ge.com (Bruce Barnett)
- Newsgroups: alt.sources
- Subject: Ease 3.0: High Level Language for Sendmail (Part 6 of 6)
- Message-ID: <BARNETT.91Feb23021920@grymoire.crd.ge.com>
- Date: 23 Feb 91 07:19:20 GMT
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 6 (of 6)."
- # Contents: cfc/cfc.c
- # Wrapped by barnett@grymoire on Sat Feb 23 01:13:56 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f cfc/cfc.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"cfc/cfc.c\"
- else
- echo shar: Extracting \"cfc/cfc.c\" \(39729 characters\)
- sed "s/^X//" >cfc/cfc.c <<'END_OF_cfc/cfc.c'
- X#ifndef lint
- Xstatic char RCSid[] = "$Header: /home/kreskin/u0/barnett/Src/ease/cfc/RCS/cfc.c,v 3.0 1991/02/22 19:33:07 barnett Exp $";
- X#endif
- X
- X/*
- X * $Log: cfc.c,v $
- X * Revision 3.0 1991/02/22 19:33:07 barnett
- X * Many enhancements for IDA and HP sendmail.cf files
- X *
- X * Revision 2.2 1991/02/21 19:19:34 barnett
- X * Fixed several bugs:
- X * Multiple ifsets on one line
- X * Better handling of # in comments
- X * Support for escaping a '* and /' in a comment field
- X *
- X * Revision 2.1 1990/01/30 11:38:10 jeff
- X * Enhancements by Bruce Barnett 89/1/23:
- X * - Added some enhancements for SunOS 4.0 and Ultrix 3.0
- X * - And a log of unusual grammar constructs
- X *
- X * Revision 2.0 88/06/15 15:16:48 root
- X * Baseline release for net posting. ADR.
- X *
- X * Revision 1.6 88/06/10 13:45:16 root
- X * Fix originally from Raymond A. Schnitzler (ras@sabre.bellcore.com) to
- X * add the (undocumented) 'P' option which sets the Postmaster address for
- X * receiving cc's of bad mail. ADR.
- X *
- X * Revision 1.5 88/01/21 16:18:13 root
- X * Eliminated Rutgers-ism, linted, smartened Mailer Argv handling. ADR.
- X *
- X * Revision 1.4 88/01/21 15:57:52 root
- X * Added the 'y' factor; missed it last time. ADR.
- X *
- X * Revision 1.3 87/04/08 10:23:02 root
- X * Small bug fixes, compatibility option added, also warnings for
- X * unrecognized flags and options. ADR.
- X *
- X * Revision 1.2 87/02/18 15:26:39 root
- X * Fix to recognize multidigit ruleset numbers in $> (calls) in RHS. ADR.
- X *
- X * Revision 1.1 87/02/16 15:25:00 arnold
- X * Initial revision
- X *
- X * Revision 1.1 87/02/16 15:25:00 arnold
- X * Initial revision
- X *
- X */
- X
- X/*
- X * cfc.c
- X *
- X * Sendmail cf file compiler.
- X * Reads a raw sendmail.cf file and produces ease source.
- X *
- X * There are very few comments in this source. You will need both the
- X * "Sendmail Installation and Operation Guide" and the paper on Ease
- X * to really understand this.
- X *
- X * Arnold Robbins
- X * Emory University Computing Center
- X * 2/87
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X
- Xchar buffer[BUFSIZ];
- Xint line = 0;
- Xint inruleset = 0;
- X
- Xextern char *macro (); /* convert sendmail to ease macro names */
- Xextern char *mflags (); /* convert sendmail to ease mailer flag names */
- Xextern char *optionname (); /* convert sendmail to ease option names */
- Xextern char *delivoption (); /* delivery options */
- Xextern char *handle_option (); /* handling options */
- X
- Xextern char *ngets (); /* buffered gets () routine */
- Xextern void ungets (); /* put a buffer back for getting */
- X
- X#define endruleset() if (inruleset) { inruleset = 0; printf ("\t}\n"); }
- X
- Xint compat = 0; /* complain about new 4.3 options & flags */
- Xint undoc = 0; /* complain about undocumented options, flags */
- Xint ida = 0; /* IDA sendmail options */
- Xint sunos = 0; /* Special parsing for SunOS - bgb */
- Xint DECos = 0; /* Special parsing for Ultrix - bgb */
- X /* NOTE: can't use 'ultrix' cause of cpp */
- Xint hpos = 0; /* HP/UX */
- X
- Xchar *classes = 0; /* list of classes defined */
- Xmain (argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X extern int getopt ();
- X extern int optind;
- X extern char *optarg;
- X int i,c;
- X
- X while ((c = getopt (argc, argv, "icdhusC:")) != EOF) {
- X switch (c) {
- X case 'c':
- X compat = 1;
- X break;
- X case 'u':
- X undoc = 1;
- X break;
- X case 's':
- X sunos = 1;
- X break;
- X case 'd':
- X DECos = 1;
- X break;
- X case 'i':
- X ida = 1;
- X break;
- X case 'h':
- X hpos = 1;
- X break;
- X case 'C':
- X classes = optarg;
- X break;
- X case '?':
- X default:
- X fprintf (stderr, "usage: %s [ -[ids] ] [ -c ] [ -u ] [-C classes ]\n", argv[0]);
- X break;
- X }
- X }
- X
- X if (optind < argc)
- X fprintf (stderr,
- X "warning: ignoring non-flag command line arguments\n");
- X
- X printf ("/***********************************************************/\n");
- X printf ("/* This ease file generated by cfc version $Revision: 3.0 $*/\n");
- X printf ("/* automatically from a sendmail.cf file */\n");
- X printf ("/* It may need to be edited before feeding to ease. */\n");
- X printf ("/***********************************************************/\n");
- X /* let's generate something that might work */
- X printf ("bind \n");
- X for (i=0;i<=29;i++)
- X printf ("\tRULESET_%d = ruleset %d;\n",i,i);
- X /* SunOS uses ruleset 30. Other sendmails only support S0 to S29 */
- X if (sunos)
- X printf ("\tRULESET_30 = ruleset 30;\n");
- X
- X /*
- X * For perfection, everything but the comment and rule cases
- X * should do an endruleset (), but practically speaking, it is
- X * usually only the mailer new ruleset definitions that end a
- X * previous ruleset. Occasionally a macro, too.
- X * Also class definitions - BGB
- X */
- X
- X while (ngets (buffer) != NULL)
- X {
- X line++;
- X switch (buffer[0]) {
- X case '#':
- X comment ();
- X continue; /* skip code to end ruleset */
- X case 'S':
- X endruleset ();
- X ruleset ();
- X continue; /* skip code to end ruleset */
- X case 'R':
- X rule ();
- X continue; /* skip code to end ruleset */
- X case 'D':
- X endruleset ();
- X def ();
- X break;
- X case 'C':
- X endruleset ();
- X class ();
- X break;
- X case 'F':
- X endruleset ();
- X fileclass ();
- X break;
- X case 'M':
- X endruleset ();
- X mailer ();
- X break;
- X case 'H':
- X header ();
- X break;
- X case 'O':
- X option ();
- X break;
- X case 'T':
- X trusted ();
- X break;
- X case 'P':
- X precedence ();
- X break;
- X default:
- X other ();
- X continue; /* skip code to end ruleset */
- X }
- X endruleset ();
- X }
- X endruleset (); /* just in case */
- X exit (0);
- X /*NOTREACHED*/
- X}
- X
- X/* comment --- produce a comment */
- X
- Xcomment ()
- X{
- X static char format[] = "/* %s */\n";
- X register int i = strlen (buffer) - 1;
- X register int j;
- X /* try to be semi-intelligent about comments */
- X
- X /* if a blank line, keep as a blank line */
- X if (buffer[1] == '\0')
- X printf ("\n");
- X else { /* non-blank comment */
- X j=1;
- X printf("/*");
- X /* print ######## as /********* */
- X while (buffer[j] == '#') {
- X j++;
- X printf("*");
- X }
- X /* print the rest of the line */
- X while (buffer[j] != '\0') {
- X switch (buffer[j]) {
- X case '#':
- X /* convert ### to *** */
- X if (buffer[j+1] == '\0') {
- X printf("*");
- X } else if (buffer[j+1] == '#') /* a string of #### */
- X while (buffer[j] == '#' && buffer[j+1] != '\0') {
- X printf("*");
- X j++;
- X }
- X else printf("#");
- X break;
- X case '*':
- X if (buffer[j+1] == '/') {
- X printf("*\\/");
- X j++;
- X } else printf("*");
- X break;
- X default:
- X printf("%c", buffer[j]);
- X break;
- X }
- X j++;
- X } /* end while */
- X if ( buffer[j-2] == '#' && buffer[j-1] == '#')
- X printf("*/\n");
- X else if ( buffer[j-2] != '#' && buffer[j-1] == '#')
- X printf("*/\n");
- X else if ( buffer[j-1] == ' ' || buffer[j-1] == '\t')
- X printf("*/\n");
- X else
- X printf(" */\n");
- X } /* end of non-blank */
- X }
- X
- X/* ruleset --- name a ruleset */
- X
- Xruleset ()
- X{
- X static int first = 1;
- X register char *cp = buffer + 1;
- X int i;
- X
- X if (first)
- X {
- X first = 0;
- X printf ("\n/* These are sample field definitons (cfc) */\n");
- X printf ("\nfield\n\tzero_or_more : match (0*);\n");
- X printf ("\tone_or_more : match (1*);\n");
- X printf ("\texactly_one : match (1);\n");
- X if (classes && *classes ) {
- X printf("\t/* defining classes %s */\n",classes);
- X for (i=0;*(classes+i);i++) {
- X printf ("\tany_in_%c : match (1) in %c;\n",*(classes+i),*(classes+i));
- X printf ("\tany_not_in_%c : match (0) in %c;\n",*(classes+i),*(classes+i));
- X }
- X }
- X /* let's make the default configuration nicer for SunOS - bgb */
- X if (DECos || ida || hpos ) {
- X printf ("\tany_in_myhostname : match (1) in c_myname;\n");
- X }
- X if (sunos) {
- X/* printf ("\tany_in_V : match (1) in V;\n");
- X printf ("\tany_not_in_V : match (0) in V;\n"); */
- X printf ("/*\tany_in_map_? : match (1) map ?;\t*/\n");
- X printf ("/*\tany_not_in_map_? : match (0) map ?;\t*/\n");
- X printf ("\tany_in_etc_hosts : match host;\n");
- X printf ("\tany_in_mydomainname : match (1) in c_mydomain;\n");
- X printf ("\tany_in_myhostname : match (1) in c_myname;\n");
- X }
- X }
- X
- X printf ("ruleset\n\tRULESET_");
- X while (cp && *cp && ! isspace (*cp))
- X {
- X putchar (*cp);
- X cp++;
- X }
- X
- X printf (" {");
- X if (*cp)
- X printf ("\t/* %s */", cp);
- X putchar ('\n');
- X inruleset++;
- X}
- X
- X/* rule --- print out a rule */
- X
- Xrule ()
- X{
- X register char *cp = buffer + 1;
- X register char *cp2;
- X register int com = 0;
- X
- X /* first, split it up into LHS, RHS, COMMENT */
- X
- X while (cp && *cp && *cp != '\t')
- X cp++;
- X if (!*cp) {
- X fprintf(stderr,
- X "Unexpected EOL when expecting right hand side of rule\n");
- X lhs(buffer+1);
- X printf("\n\tMissingRightHandSide();\n");
- X return;
- X }
- X *cp = '\0';
- X
- X cp++;
- X while (cp && *cp && *cp == '\t')
- X cp++;
- X cp2 = cp;
- X while (cp && *cp && *cp != '\t')
- X cp++;
- X if (*cp == '\t' && cp[1])
- X {
- X *cp = '\0';
- X com++;
- X cp++;
- X while (cp && *cp && *cp == '\t')
- X cp++;
- X }
- X
- X /* now print */
- X lhs (buffer + 1); /* left hand side */
- X if (com)
- X printf ("\t/* %s */", cp);
- X putchar ('\n');
- X rhs (cp2); /* right hand side */
- X}
- X
- X/* lhs --- left hand side of a production */
- X
- Xlhs (text)
- Xchar *text;
- X{
- X register char *cp = text;
- X register int conditional = 0;
- X register int quoting = 0;
- X register int open = 0;
- X int ifset = 0;
- X
- X printf ("\tif (");
- X for (; *cp; cp++)
- X {
- X switch (*cp) {
- X case '$':
- X if (quoting)
- X {
- X quoting = 0;
- X putchar ('"');
- X }
- X switch (*++cp) {
- X case '*':
- X printf (" zero_or_more ");
- X break;
- X case '+':
- X printf (" one_or_more ");
- X break;
- X case '-':
- X printf (" exactly_one ");
- X break;
- X case '=':
- X switch(*++cp) {
- X case 'w':
- X if (sunos || ida || DECos ) {
- X printf (" any_in_myhostname ");
- X break;
- X } /* else fall through */
- X case 'm':
- X if (sunos ) {
- X printf (" any_in_mydomainname ");
- X break;
- X } /* else fall through */
- X default :
- X printf (" any_in_%c ", *cp);
- X }
- X break;
- X case '%' :
- X /* YP map for SunOS */
- X if ((cp+1) && sunos && (*(cp +1) == 'y') ) {
- X printf (" any_in_etc_hosts"); ++cp;
- X } else {
- X printf (" any_in_map_%c", *++cp);
- X }
- X break;
- X case '~':
- X printf (" any_not_in_%c ", *++cp);
- X break;
- X case '?':
- X printf (" ifset (%s, ", macro (*++cp));
- X conditional++;ifset++;
- X break;
- X case '|':
- X if ( ! conditional) die("lhs - $| without $?");
- X if ( ifset) {
- X printf("\", \"");
- X } else {
- X fprintf(stderr,"Got $| when not in ifset\n");
- X putchar (',');
- X }
- X break;
- X case '{':
- X printf("ypalias ("); /* Ultrix */
- X open++;
- X break;
- X case '"':
- X printf("yppasswd ("); /* Ultrix */
- X open++;
- X break;
- X case '.':
- X putchar (')');
- X conditional--;ifset--;
- X break;
- X case '#':
- X /* IDA does something strange with this */
- X printf("resolved(");
- X open++;
- X break;
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X printf ("$%c", *cp);
- X break;
- X default:
- X if (quoting)
- X printf ("${%s}", macro (*cp));
- X else
- X printf ("$%s", macro (*cp));
- X break;
- X }
- X break;
- X default:
- X if (ispunct (*cp))
- X {
- X if (quoting) /* end a literal */
- X {
- X quoting = 0;
- X putchar ('"');
- X }
- X /* else
- X do nothing */
- X }
- X else
- X {
- X /* start a literal - but ignore the first space */
- X if (*cp != ' ' && ! quoting)
- X {
- X quoting = 1;
- X putchar ('"');
- X }
- X /* else
- X do nothing */
- X }
- X putchar (*cp); /* print the character */
- X break;
- X }
- X }
- X if (quoting)
- X putchar ('"');
- X while (open--)
- X putchar (')');
- X if (conditional)
- X die ("lhs");
- X printf (")");
- X}
- X
- X/* rhs --- right hand side of a production */
- X
- Xrhs (text)
- Xchar *text;
- X{
- X register char *cp = text;
- X char *index ();
- X char *cp1;
- X register int open = 0;
- X register int conditional = 0; /* true if in an ifset condition */
- X register int quoting = 0; /* true if in a string */
- X register int ifset = 0; /* true if in ifset(), like quoting */
- X register int needconcat = 0; /* true if an $? on line (lookahead) */
- X register int didconcat = 0; /* true if did the concat() */
- X register int indbm = 0; /* true if in IDA $( $) construct */
- X register int inalias = 0; /* true if in IDA $(@ $) construct */
- X int canon = 0;
- X int diddefault = 0;
- X
- X printf ("\t\t");
- X
- X /* Need to handle this line */
- X /* R$+<@$=S> $:$1<@$2>$?R<$R>$. */
- X for(cp1=cp;*cp1;cp1++) {
- X if (*cp1 == '$' && (cp1+1) && *(cp1+1)== '?')
- X needconcat = 1; /* there is an ifset on this line */
- X }
- X if (*cp == '$' && index ("#@:", cp[1]) != NULL)
- X ; /* not the default */
- X else
- X {
- X printf ("retry (");
- X open++;
- X }
- X
- X for (; *cp; cp++)
- X {
- X switch (*cp) {
- X case '$':
- X if (quoting && ! ifset )
- X {
- X quoting = 0;
- X putchar ('"');
- X }
- X switch (*++cp) {
- X case '>':
- X printf ("RULESET_");
- X for (cp++; cp && *cp && isdigit (*cp); cp++)
- X putchar (*cp);
- X cp--;
- X printf (" (");
- X open++;
- X break;
- X case '[':
- X if (quoting) {
- X putchar('"');
- X quoting--;
- X }
- X printf (" canon (");
- X open++; canon++;
- X break;
- X case ']':
- X putchar (')');
- X open--;
- X if (diddefault) {
- X putchar (')');
- X diddefault--;
- X }
- X break;
- X case '{':
- X printf ("ypmap (%s, ", macro (*++cp)); /* sunos */
- X open++;
- X break;
- X case '}':
- X putchar (')');
- X open--;
- X break;
- X case '<':
- X printf ("program (%s, ", macro (*++cp)); /* HP/UX */
- X open++;
- X break;
- X case '?':
- X if (didconcat) {
- X printf ("\",");
- X needconcat = 0; /* don't need this */
- X }
- X printf ("ifset (%s, \"", macro (*++cp));
- X conditional++;
- X ifset++;
- X quoting++;
- X break;
- X case '|':
- X if ( ! conditional) die("rhs - $| without $?");
- X if ( ifset) {
- X printf("\", \"");
- X } else {
- X fprintf(stderr,"Got $| when not in ifset\n");
- X putchar (',');
- X }
- X break;
- X case '.':
- X if (ifset && quoting ) {
- X putchar('"'); quoting--;
- X }
- X if (! ifset ) fprintf(stderr,"Got $. while not in ifset\n");
- X putchar (')');
- X if (open) {
- X putchar(')');
- X open--;
- X }
- X conditional--;
- X ifset--;
- X break;
- X case '#':
- X parseresolve(cp);
- X goto out; /* string is exhausted */
- X /* break; */
- X case '@':
- X if ( ! indbm) {
- X printf ("return (");
- X if (needconcat && cp+1 && cp+2 &&
- X ! ((*(cp+1) == '$') && (*(cp+2) == '?'))){
- X printf ("concat (\"");
- X open++;didconcat++;
- X }
- X open++;
- X } else {
- X printf("\", \"");
- X }
- X break;
- X case ':':
- X if ( canon ) {
- X printf("default ( ");
- X canon--;diddefault++;
- X } else if ( indbm ) {
- X printf("default ( ");
- X indbm--;diddefault++;
- X } else {
- X printf ("next (");
- X if (needconcat && cp+1 && cp+2 &&
- X ! ((*(cp+1) == '$') && (*(cp+2) == '?'))){
- X printf ("concat (\"");
- X open++;didconcat++;
- X }
- X open++;
- X }
- X break;
- X case '(':
- X if (*(cp+1) == '@') { /* then IDA alias lookup */
- X cp++; /* point past '@' */
- X printf("alias(");
- X indbm++;
- X open++;
- X } else { /* lookup */
- X printf("dbm(");
- X printf("$%s, \"",macro(*cp++));
- X }
- X break;
- X case ')':
- X printf("))");
- X open--;
- X indbm--;
- X break;
- X case '&':
- X printf(" eval(%s) ",macro(*(++cp)));
- X break;
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X printf ("$%c", *cp);
- X break;
- X default:
- X if (ifset ) {
- X if (quoting)
- X printf ("${%s}", macro (*cp));
- X else
- X printf ("$%s", macro (*cp));
- X } else { /* not not in ifset() */
- X if (quoting)
- X printf ("${%s}", macro (*cp));
- X else
- X printf ("$%s", macro (*cp));
- X }
- X break;
- X }
- X break; /* not a character that starts with a $ */
- X default:
- X if ( ifset && quoting ) {
- X putchar(*cp);
- X } else if (ifset && ! quoting) {
- X if ( ispunct (*cp)) {
- X putchar('"');quoting++;
- X }
- X putchar(*cp);
- X } else { /* not ifset */
- X if (ispunct (*cp))
- X {
- X if (quoting ) /* end a literal */
- X {
- X quoting = 0;
- X putchar ('"');
- X }
- X /* else
- X do nothing */
- X } else {
- X if (*cp != ' ' && ! quoting) /* start a literal */
- X {
- X quoting = 1;
- X putchar ('"');
- X }
- X /* else
- X do nothing */
- X }
- X putchar (*cp); /* print the character */
- X }
- X break;
- X }
- X } /* end of for */
- Xout:
- X if (quoting)
- X putchar ('"');
- X while (open--)
- X putchar (')');
- X printf (";\n");
- X if (conditional)
- X die ("rhs - $? without $.");
- X}
- X/* parseresolve - parse this mailer/host/user mess */
- Xparseresolve(cp)
- Xchar *cp;
- X{
- X int quoting = 0;
- X int open = 0;
- X char *addrops;
- X addrops = ".:;%@!=/[]?#^,<>$"; /* should be defined from input file */
- X printf ("resolve (mailer (");
- X/* if (strncmp (cp+1, "local", 5) == 0
- X || strncmp (cp+1, "error", 5) == 0
- X || strncmp (cp+1, "LOCAL", 5) == 0
- X || strncmp (cp+1, "ERROR", 5) == 0)
- X goto skiphost;
- Xloop1:
- X*/
- X /* this is a simple parser that scans the right
- X hand side of a $# rule
- X The format is usually
- X "$# mailer $@ host $: user" or
- X "$# mailer $: user" or
- X "$# mailer $: something with a $macro" or
- X "$# $M $: user" or
- X "$# $1 " (IDA sendmail )
- X
- X Note that there may be special constructs
- X in the host field, i.e.
- X "$1", "[$2]", "$w", or "$K".
- X and in the user field. Esp. in the error mailer:
- X "$1 < @$2 > $4", or
- X "Never heard of host $2 in domain $m "
- X "$n" which should become -> "$m_daemon"
- X */
- X /* pointing to '#' */
- X cp++;
- X /* output any character not a '$' */
- X while (cp && *cp && *cp != '$' ) {
- X /* skip spaces in the mailer field */
- X if ( *cp != ' ' ) putchar(*cp);
- X cp++;
- X }
- X if (!cp || !*cp ) goto out;
- X /* currently pointing to a "$" */
- X /* we may now be pointing to:
- X $@ - the host name
- X $: - the user
- X or a macro
- X or nothing?! (*cp == 0);
- X /* don't look at the '$' */
- X cp++;
- X if (!cp || !*cp ) goto out;
- X if (*cp == ':') goto parseuser;
- X if (*cp != '@' ) {
- X /* must be a macro name */
- X printf ("$%s",macro(*cp++));
- X /* now skip to the $@ */
- X if (!cp || !*cp ) goto out;
- X while (cp && *cp && *cp == ' ') cp++;
- X if (!cp || !*cp ) goto out;
- X if (*cp == '$') cp++;
- X else
- X fprintf(stderr,
- X "Error: found %c when expecting a '$' on line %d\n",
- X *cp,line);
- X if (*cp == ':') goto parseuser;
- X if (*cp == '@') cp++;
- X else
- X fprintf(stderr,
- X "Error: found %c when expecting a '@' on line %d\n",
- X *cp,line);
- X } else {
- X /* I did see the '@' of the $@ */
- X cp++;
- X }
- X /* print host name ($@host ) */
- X printf ("),\n\t\t\t\thost (");
- X for (;cp && *cp;cp++) {
- X if (*cp != '$') {
- X putchar (*cp);
- X } else {
- X /* it might be the $: */
- X if (!*(cp+1)) goto out;
- X if ( *(cp+1) == ':') {
- X cp++; /* parseuser expects ':' */
- X goto parseuser;
- X } else {
- X putchar(*cp++); /* print '$' */
- X printf("%s", macro(*cp)); /* and next */
- X }
- X }
- X }
- X parseuser:
- X printf ("),\n\t\t\t\tuser (");
- X /* *cp == ':', now look for user = $n */
- X /* maybe *cp == 0 */
- X if ( !*cp ) goto out;
- X if (*cp != ':' )
- X fprintf(stderr,
- X "Expected ':', found '%c' after '$' on line %d\n",*cp,line);
- X /* looking at the user string */
- X quoting = 0;
- X for (cp++; cp && *cp; cp++) {
- X if (quoting ) {
- X/* if (isalnum(*cp) || isspace(*cp)) { */
- X if (*cp == '"') {
- X printf("\\\""); /* print "\" */
- X quoting++;
- X } else if (*cp == '\\') {
- X printf("\\"); /* print "\" and the next character */
- X putchar(*++cp);
- X } else if (!index(addrops,*cp)) {
- X /* not one of those address characters */
- X putchar (*cp);
- X } else { /* maybe it's a dollar sign? */
- X quoting=0;
- X printf("\" %c",*cp);
- X if (*cp == '$') {
- X cp++; /* This may not be used at all - but it can't hurt */
- X if (*cp == '>' ) { /* IDA sendmail */
- X cp++;
- X printf(" RULESET_");
- X while (cp && *cp && *cp >= '0' && *cp <= '9') putchar(*cp++);
- X printf("(");
- X open++;
- X } else {
- X printf("%s",macro(*cp));
- X }
- X }
- X }
- X } else { /* not quoting */
- X if ( *cp == '$' ) {
- X cp++;
- X if (*cp == '>' ) { /* IDA sendmail */
- X cp++;
- X printf("retry (RULESET_");
- X while (cp && *cp && *cp >= '0' && *cp <= '9') putchar(*cp++);
- X printf("("); open++;
- X open++;
- X } else {
- X putchar ('$'); /* print $ */
- X printf("%s",macro(*cp)); /* and macro */
- X }
- X } else if (*cp && (index (addrops,*cp))) {
- X putchar(*cp);
- X } else if (*cp == '"') {
- X printf("\"\\\"");quoting++; /* print "\" */
- X } else {
- X quoting = 1;
- X printf(" \"%c",*cp);
- X }
- X } /* end of quoting/not quoting */
- X }
- X if (quoting) printf("\"");
- X out:
- X while (open--) printf(")");
- X printf ("))");
- X} /* end parseresolve () */
- X/* def --- define a macro */
- X
- Xdef ()
- X{
- X register char *mac = buffer + 1, *value = buffer + 2;
- X register int conditional = 0;
- X register int concat = 0;
- X register int quote = 0;
- X register int ifset = 0;
- X
- X
- X printf ("macro\n\t%s = ", macro (*mac));
- X/* fprintf(stderr,"mac=%c, value=%s\n",*mac,value); */
- X
- X/* This is tricky, we want the form:
- X *
- X * Dq$g$?x$x$.
- X * to become
- X * macro
- X * m_defaddr = concat ("${m_sreladdr}", ifset (m_sname," (${m_sname})"));
- X * and
- X * Dq$?x$x $.<$g>
- X * to become
- X * macro
- X * m_defaddr = concat (ifset (m_sname," (${m_sname})"),"<${m_sreladdr}>" );
- X *
- X * One problem is the form
- X * Dq$?x$x <$g>$|$g$.
- X *
- X *
- X */
- X concat = 0;
- X quote = 0;
- X conditional = 0;
- X ifset = 0;
- X if (! *value ) printf("\"\""); /* unusual error - just print " and let
- X the end of the loop after the while
- X clean it up */
- X while (*value)
- X {
- X switch (*value) {
- X case '$':
- X switch (*++value) {
- X /* $:$?E$1%$2.dnet<@$E.LOCAL>$3$|$1<@$2.dnet>$3$.
- X Dq$?x$x <$g>$|$g$.
- X Dq$?x$!x <$g>$|$g$.
- X */
- X case '?':
- X /* Another special case %$&*!
- X * if the start of the string is $?,
- X * but the end is NOT $., then we need a concat
- X */
- X if (*(value+strlen(value)-1) == '.' &&
- X *(value+strlen(value)-2) == '$') {
- X /* just use ifset with no concat */
- X printf ("ifset (%s, ", macro (*++value));
- X conditional++;ifset++;
- X /* Still need a quote character,
- X next characters might be a $!x */
- X if ((*(value+1) == '$') && (*(value+2) == '!')) {
- X value++;value++;
- X printf("\"${quote(%s)} ",macro(*++value));
- X quote++;
- X } else {
- X printf("\"");quote++;
- X }
- X } else {
- X printf ("concat( ifset (%s, \"", macro (*++value));
- X conditional++;quote++;concat++;ifset++;
- X }
- X break;
- X case '|':
- X if ( ! conditional) die("def - $| without $?");
- X if ( ifset) {
- X printf("\", \"");
- X } else {
- X fprintf(stderr,"Got $| when not in ifset\n");
- X putchar (',');
- X }
- X break;
- X case '.':
- X if (quote) {
- X putchar('"');quote--;
- X }
- X putchar (')');
- X conditional--;ifset--;
- X /* not EOL, must be in concat(ifset( ,) */
- X if (*(value+1)) putchar(',');
- X break;
- X case '!': /* IDA sendmail - this code never gets executed */
- X printf("quote("); concat++;
- X break;
- X default:
- X /* see if *(value+1) == '$' and *(value+2) == '?' */
- X if (!concat && (strlen(value)>2)
- X && (*(value+1) == '$')
- X && (*(value+2) == '?')) {
- X printf ("concat (\"${%s}\", ", macro (*value));
- X /* I'm gonna need a concat */
- X concat++;
- X } else {
- X if (!quote) {
- X printf("\"${%s}", macro (*value));
- X quote++;
- X } else {
- X printf ("${%s}", macro (*value));
- X }
- X }
- X break;
- X }
- X break;
- X case '"' :
- X if (quote) {
- X printf ("\\\"");
- X } else {
- X printf("\"\\\"");
- X quote++;
- X }
- X break;
- X default:
- X if ( ! quote ) {
- X putchar('"');
- X quote++;
- X }
- X putchar (*value);
- X break;
- X }
- X value++;
- X }
- X if ( quote ) putchar('"');
- X if (concat) {
- X putchar (')');
- X concat--;
- X }
- X printf (";\n");
- X if (conditional)
- X die ("def - $? without $.");
- X}
- X
- X/* class --- define a class list */
- X
- Xclass ()
- X{
- X register char *name = buffer + 1, *value = buffer + 2;
- X int havepunct;
- X char *s;
- X
- X
- X printf ("class\n\t");
- X switch (name[0]) {
- X case 'w' : printf("c_myname"); break;
- X case 'm' : if (sunos) { printf("c_mydomain"); break; }
- X /* fall through if not SunOS */
- X default: printf("%c",name[0]);
- X }
- X
- X printf (" = { ");
- X
- X while (value && *value && isspace (*value))
- X value++;
- X
- X /* a class may be a series of punctuation characters e.g. IDA */
- X /* also watch for spaces on the end of a line and avoid ',)' */
- X
- X while (value && *value)
- X {
- X /* get first field */
- X /* look for first space or EOL */
- X for (s=value,havepunct=0;*s && ! isspace (*s);s++)
- X if (ispunct(*s)) havepunct = 1;
- X
- X /* field is from *value to *s
- X if there is a punctuation char, havepunt == 1 */
- X if (havepunct) putchar('"');
- X while (value < s ) {
- X if (*value == '"') putchar('\\'); /* escape quotes */
- X if (*value == '$' ) printf ("${%s}", macro (*++value));
- X else putchar(*value);
- X value++;
- X }
- X if (havepunct) putchar('"');
- X /* if not EOL, put a comma there
- X but watch out for extra spaces.....
- X
- X so scan over spaces, then look at the next character.
- X If not EOL, print ", ". */
- X
- X while (value && *value && isspace(*value)) value++;
- X if (*value && !isspace(*value)) printf (", ");
- X }
- X printf (" };\n");
- X}
- X
- X/* fileclass --- define a class that is to be read from a file */
- X
- Xfileclass ()
- X{
- X register char *name = buffer + 1, *value = buffer + 2;
- X
- X printf ("class\n\t%c = readclass (\"", *name);
- X for (; *value && !isspace (*value); value++)
- X putchar (*value);
- X putchar ('"');
- X while (value && *value && isspace (*value))
- X value++;
- X if (*value)
- X printf (", \"%s\"", value);
- X printf (");\n");
- X}
- X
- X/* mailer --- convert a mailer specification */
- X
- Xmailer ()
- X{
- X register char *cp = buffer + 1;
- X
- X printf ("mailer\n\t");
- X for (; *cp != ','; cp++)
- X putchar (*cp);
- X cp++;
- X printf (" {\n"); /* just did mailer name */
- X
- X#define skipname() cp++; while (cp && *cp && *cp != '=') cp++; cp++
- X#define value() for (; cp && *cp && *cp != ','; cp++) putchar (*cp); cp++
- X
- Xloop:
- X while (cp && *cp && isspace (*cp))
- X cp++;
- X
- X printf ("\t\t");
- X switch (*cp) {
- X case 'A':
- X skipname ();
- X printf ("Argv = \"");
- X for (; *cp && *cp != ','; cp++)
- X {
- X if (*cp == '$') /* XXX: assume no conditionals */
- X printf ("${%s}", macro (*++cp));
- X else if (*cp == '"')
- X printf ("\\\"");
- X else
- X putchar (*cp);
- X }
- X cp++; /* do manually what value does */
- X putchar ('"');
- X break;
- X
- X case 'E':
- X skipname ();
- X printf ("Eol = \"");
- X value ();
- X putchar ('"');
- X break;
- X
- X case 'F':
- X skipname ();
- X printf ("Flags = { ");
- X for (; *cp && *cp != ','; cp++)
- X {
- X printf ("%s", mflags (*cp));
- X if (cp[1] && cp[1] != ',')
- X printf (", ");
- X }
- X cp++; /* do manually what value does */
- X printf (" }");
- X break;
- X
- X case 'M':
- X skipname ();
- X printf ("Maxsize = \"");
- X value ();
- X putchar ('"');
- X break;
- X
- X case 'P':
- X skipname ();
- X printf ("Path = \"");
- X value ();
- X putchar ('"');
- X break;
- X
- X case 'R':
- X skipname ();
- X printf ("Recipient = RULESET_");
- X /* IDA has ruleset/ruleset */
- X for (; *cp && *cp != ',' && *cp != '/'; cp++)
- X putchar (*cp);
- X if (ida && cp && (*cp == '/' )) {
- X putchar (*cp++);
- X printf("RULESET_");
- X value ();
- X } else {
- X cp++ ;
- X }
- X break;
- X
- X case 'S':
- X skipname ();
- X printf ("Sender = RULESET_");
- X /* IDA has ruleset/ruleset */
- X for (; *cp && *cp != ',' && *cp != '/'; cp++)
- X putchar (*cp);
- X if (ida && cp && (*cp == '/' )) {
- X putchar (*cp++);
- X printf("RULESET_");
- X value ();
- X } else {
- X cp++ ;
- X }
- X break;
- X
- X case '\0':
- X goto done;
- X }
- X
- X if (cp[-1] && cp[-1] == ',')
- X {
- X printf (",\n");
- X goto loop;
- X }
- X else
- X putchar ('\n');
- X
- Xdone:
- X /* handle continuation lines */
- X if (ngets (buffer) != NULL)
- X {
- X line++;
- X if (buffer[0] == '\t')
- X {
- X cp = buffer;
- X goto loop;
- X }
- X else
- X ungets (buffer);
- X }
- X else
- X ungets ((char *) NULL);
- X
- X printf ("\t};\n");
- X
- X#undef value
- X#undef skipname
- X}
- X
- X/* header --- define sendmail headers */
- X
- Xheader ()
- X{
- X register char *cp = buffer + 1;
- X register int flags = 0;
- X register int conditional = 0;
- X register int concat = 0;
- X register int quote = 0;
- X register int ifset = 0;
- X
- X printf ("header\n\t");
- X if (*cp == '?') /* header for mailers with these flags */
- X {
- X flags++;
- X printf ("for (");
- X for (cp++; cp && *cp != '?'; cp++)
- X {
- X printf ("%s", mflags (*cp));
- X if (cp[1] != '?')
- X putchar (',');
- X }
- X printf (") {\n\t\t");
- X cp++; /* skip final '?' */
- X }
- X
- X printf ("define (\"");
- X for (; *cp && ! isspace (*cp); cp++)
- X putchar (*cp);
- X /* skip over any spaces */
- X while ( cp && *cp && isspace(*cp)) cp++;
- X /* but if we are now at the end of the line, we must fake
- X an entry for "" */
- X if ( cp && *cp ) printf ("\", "); /* don't print next " yet, see if it is a concat */
- X else if (cp && ! *cp ) printf("\", \"\"");
- X else if (!cp) {
- X printf("\"");
- X fprintf(stderr,"I didn't expect this!\n");
- X }
- X
- X quote = concat = conditional = ifset = 0;
- Xbody:
- X while (cp && *cp)
- X {
- X switch (*cp) {
- X case '$':
- X switch (*++cp) {
- X case '?':
- X /* if we are not in a concat, then start one */
- X if ( ! concat ) {
- X printf("concat (");
- X concat++;
- X } else { /* we are in one */
- X if (quote) {
- X printf("\"");quote--;
- X }
- X printf("), concat (");
- X }
- X if (quote) {
- X printf("\",");quote--;
- X }
- X printf ("ifset (%s, \"", macro (*++cp));
- X conditional++; quote++;ifset++;
- X break;
- X case '|':
- X if ( ! conditional) die("header - $| without $?");
- X if ( ifset) {
- X printf("\", \"");
- X } else {
- X fprintf(stderr,"Got $| when not in ifset\n");
- X putchar (',');
- X }
- X break;
- X case '.':
- X if (quote) {
- X putchar('"');quote--;
- X }
- X putchar (')');
- X conditional--;ifset--;
- X if (concat) {
- X /* this is messy - There may be more than one $? on a line */
- X
- X if (cp+1) { /* if there is more on the line */
- X printf(", ");
- X }
- X }
- X break;
- X default: /* a $<letter> */
- X /* see if *(cp+1) == '$' and *(cp+2) == '?' */
- X if (!concat && (strlen(cp)>2)
- X && (*(cp+1) == '$')
- X && (*(cp+2) == '?')) {
- X printf ("concat (\"${%s}\", ", macro (*cp));
- X /* I'm gonna need a concat */
- X concat++;
- X } else {
- X if (!quote) {
- X printf("\"${%s}", macro (*cp));
- X quote++;
- X } else {
- X printf ("${%s}", macro (*cp));
- X }
- X }
- X break;
- X }
- X break;
- X case '"' :
- X printf ("\\\"");
- X break;
- X default:
- X if ( ! quote ) {
- X putchar('"');
- X quote++;
- X }
- X putchar (*cp);
- X break;
- X }
- X cp++;
- X }
- X
- X /* handle continuation lines */
- X if (ngets (buffer) != NULL)
- X {
- X line++;
- X if (buffer[0] == '\t')
- X {
- X if ( ! quote ) {
- X putchar('"');
- X quote++;
- X }
- X printf ("\\\n");
- X cp = buffer + 1;
- X
- X goto body;
- X }
- X else
- X ungets (buffer);
- X }
- X else
- X ungets ((char *) NULL);
- X
- X if ( quote ) {
- X putchar('"');
- X }
- X if (concat) {
- X putchar(')');
- X concat--;
- X }
- X printf (");\n");
- X
- X if (flags)
- X printf ("\t};\n");
- X
- X if (conditional)
- X die ("header translation problem: $? without $.");
- X}
- X
- X/* option --- translate a sendmail option to an ease option */
- X
- Xoption ()
- X{
- X register char *name = buffer + 1, *value = buffer + 2;
- X
- X printf ("options\n\t");
- X if (*name == 'd') /* delivery */
- X printf ("o_delivery = %s;\n", delivoption (*value));
- X else if (*name == 'e') /* handling */
- X printf ("o_handling = %s;\n", handle_option (*value));
- X else
- X printf ("%s = \"%s\";\n", optionname (*name), value);
- X}
- X
- X/* trusted --- define the list of trusted users */
- X
- Xtrusted ()
- X{
- X register char *cp = buffer + 1;
- X
- X if ( *cp && *cp == ' ') cp++; /* skip over spaces in the begining */
- X while (cp && *cp)
- X {
- X if (isspace (*cp))
- X *cp = ',';
- X cp++;
- X }
- X printf ("trusted\n\t{ %s };\n", buffer+1);
- X}
- X
- X/* precedence --- define the precedence of a message class */
- X
- Xprecedence ()
- X{
- X register char *cp = buffer + 1;
- X
- X printf ("precedence\n\t");
- X for (; *cp && *cp != '='; cp++)
- X putchar (*cp);
- X printf (" = %s;\n", ++cp);
- X}
- X
- X/* other --- not a sendmail control line */
- X/* it may also be a blank line */
- X
- Xother ()
- X{
- X printf ("%s\n", buffer);
- X}
- X
- Xdie (routine)
- Xchar *routine;
- X{
- X fprintf (stderr, "%s: malformed input line %d: fatal error\n",
- X routine, line);
- X exit (1);
- X}
- X
- X/* macro --- return name for sendmail predefined macro */
- X
- Xchar *macro (c)
- Xchar c;
- X{
- X static char buf[2] = { '\0', '\0' };
- X
- X switch (c) {
- X case 'a': /* The origination date in Arpanet format */
- X return ("m_odate");
- X
- X case 'b': /* The current date in Arpanet format */
- X return ("m_adate");
- X
- X case 'c': /* The hop count */
- X return ("m_hops");
- X
- X case 'd': /* The date in UNIX (ctime) format */
- X return ("m_udate");
- X
- X case 'e': /* The SMTP entry message */
- X return ("m_smtp");
- X
- X case 'f': /* The sender (from) address */
- X return ("m_saddr");
- X
- X case 'g': /* The sender address relative to the recipient */
- X return ("m_sreladdr");
- X
- X case 'h': /* The recipient host */
- X return ("m_rhost");
- X
- X case 'i': /* The queue id */
- X return ("m_qid");
- X
- X case 'j': /* The official domain name for this site */
- X return ("m_oname");
- X
- X case 'k': /* The official domain name for this site */
- X return ("m_uucpname"); /* IDA */
- X
- X case 'l': /* The format of the UNIX from line */
- X return ("m_ufrom");
- X
- X case 'm': /* The Domain Name (SunOS) */
- X if (sunos) {
- X return ("m_domain");
- X } else {
- X buf[0] = c;
- X return (buf);
- X }
- X
- X case 'n': /* The name of the daemon (for error messages) */
- X return ("m_daemon");
- X
- X case 'o': /* The set of "operators" in addresses */
- X return ("m_addrops");
- X
- X case 'p': /* Sendmail's pid */
- X return ("m_pid");
- X
- X case 'q': /* The default format of sender address */
- X return ("m_defaddr");
- X
- X case 'r': /* Protocol used */
- X return ("m_protocol");
- X
- X case 's': /* Sender's host name */
- X return ("m_shostname");
- X
- X case 't': /* A numeric representation of the current time */
- X return ("m_ctime");
- X
- X case 'u': /* The recipient user */
- X return ("m_ruser");
- X
- X case 'v': /* The version number of sendmail */
- X return ("m_version");
- X
- X case 'w': /* The hostname of this site */
- X return ("m_sitename");
- X
- X case 'x': /* The full name of the sender */
- X return ("m_sname");
- X
- X case 'y': /* The id of the sender's tty */
- X return ("m_stty");
- X
- X case 'z': /* The home directory of the recipient */
- X return ("m_rhdir");
- X
- X case '"': /* you can get a quote charater in some macro definitions */
- X return ("\\\"");
- X default:
- X buf[0] = c;
- X return (buf);
- X }
- X}
- X
- X#define docompat(val) if (compat) goto warn; else return (val)
- X#define dofundoc(val) if (undoc) \
- Xfprintf (stderr, "warning: undocumented flag '%c' used on line %d\n", c, line);\
- Xreturn (val)
- X
- X/* mflags --- convert sendmail mailer flags to ease names */
- X
- Xchar *mflags (c)
- Xchar c;
- X{
- X static char buf[2] = { '\0', '\0' };
- X
- X switch (c) {
- X case 'f': return ("f_ffrom");
- X case 'r': return ("f_rfrom");
- X case 'S': return ("f_noreset");
- X case 'n': return ("f_noufrom");
- X case 'l': return ("f_locm");
- X case 's': return ("f_strip");
- X case 'm': return ("f_mult");
- X case 'F': return ("f_from");
- X case 'D': return ("f_date");
- X case 'M': return ("f_mesg");
- X case 'x': return ("f_full");
- X case 'P': return ("f_return");
- X case 'u': return ("f_upperu");
- X case 'h': return ("f_upperh");
- X case 'H': return ("f_mail11"); /* Ultrix 3.0 */
- X case 'A': return ("f_arpa");
- X case 'U': return ("f_ufrom");
- X case 'e': return ("f_expensive");
- X case 'X': return ("f_dot");
- X case 'L': return ("f_llimit");
- X case 'p': return ("f_retsmtp");
- X case 'I': return ("f_smtp");
- X case 'C': return ("f_addrw");
- X case 'E': docompat ("f_escape");
- X case 'R': dofundoc ("f_rport");
- X case 'B': return ("f_bsmtp"); /* IDA sendmail */
- X case 'V': return ("f_relativize"); /* IDA sendmail */
- X default:
- X warn:
- X fprintf (stderr,
- X "warning: non standard mailer flag '%c' on line %d\n",
- X c, line);
- X buf[0] = c;
- X return buf;
- X }
- X}
- X
- X#define doOundoc(val) if (undoc) \
- Xfprintf (stderr, "warning: undocumented option '%c' used on line %d\n", c, line);\
- Xreturn (val)
- X
- X/* optionname --- convert sendmail options to ease names */
- X
- Xchar *optionname (c)
- Xchar c;
- X{
- X static char buf[2] = { '\0', '\0' };
- X
- X switch (c) {
- X case 'A': return ("o_alias");
- X case 'a': return ("o_ewait");
- X case 'B': return ("o_bsub");
- X case 'b': return ("o_maxempty"); /* SunOS 4.0 */
- X case 'C': doOundoc ("o_checkpoint");
- X case 'c': return ("o_qwait");
- X case 'd': return ("o_delivery");
- X case 'D': return ("o_rebuild");
- X case 'e': return ("o_handling");
- X case 'F': return ("o_tmode");
- X case 'f': return ("o_usave");
- X case 'g': return ("o_gid");
- X case 'H': return ("o_fsmtp");
- X case 'h': return ("o_maxhops"); /* SunOS 4.0 */
- X case 'i': return ("o_skipd");
- X case 'I': return ("o_nameserver"); /* HP/UX */
- X/* case 'K': Keyed Database (IDA) */
- X case 'L': return ("o_slog");
- X case 'm': return ("o_rsend");
- X case 'N': return ("o_dnet");
- X case 'n': doOundoc ("o_validate");
- X case 'o': return ("o_hformat");
- X case 'P': doOundoc ("o_pmaster");
- X case 'Q': return ("o_qdir");
- X case 'q': docompat ("o_qfactor");
- X case 'r': return ("o_tread");
- X case 'R': return ("o_nfs"); /* SunOS 4.0 */
- X case 'S': return ("o_flog");
- X case 's': return ("o_safe");
- X case 'T': return ("o_qtimeout");
- X case 't': return ("o_timezone");
- X case 'u': return ("o_dmuid");
- X case 'v': return ("o_verbose");
- X case 'W': return ("o_wizpass");
- X case 'x': return ("o_loadq");
- X case 'X': return ("o_loadnc");
- X case 'Y': if (sunos ) return ("o_aliasfile"); else docompat ("o_newproc");
- X case 'y': docompat ("o_recipfactor");
- X case 'z': docompat ("o_prifactor");
- X case 'Z': docompat ("o_waitfactor");
- X case '/': return ("o_envelope"); /* IDA */
- X default:
- X warn:
- X fprintf (stderr,
- X "warning: non standard option '%c' on line %d\n",
- X c, line);
- X buf[0] = c;
- X return buf;
- X }
- X}
- X
- X/* delivoption --- convert sendmail delivery option value to ease name */
- X
- Xchar *delivoption (c)
- Xchar c;
- X{
- X static char buf[2] = { '\0', '\0' };
- X
- X switch (c) {
- X case 'i': return ("d_interactive");
- X case 'b': return ("d_background");
- X case 'q': return ("d_queue");
- X default:
- X fprintf (stderr,
- X "warning: non standard delivery option '%c' on line %d\n", c, line);
- X buf[0] = c;
- X return buf;
- X }
- X}
- X
- X/* handle_option --- convert sendmail handling option value to ease name */
- X
- Xchar *handle_option (c)
- Xchar c;
- X{
- X static char buf[2] = { '\0', '\0' };
- X
- X switch (c) {
- X case 'p': return ("h_print");
- X case 'q': return ("h_exit");
- X case 'm': return ("h_mail");
- X case 'w': return ("h_write");
- X case 'e': return ("h_mailz");
- X default:
- X fprintf (stderr,
- X "warning: non standard handling option '%c' on line %d\n", c, line);
- X buf[0] = c;
- X return buf;
- X }
- X}
- X
- X/*
- X * "buffered" i/o routines. These are necessary since
- X * mail headers may have continuation lines, and we can't see if
- X * a continuation line is there without getting it. If it isn't,
- X * just put it back.
- X */
- X
- Xint saved = 0;
- Xchar *saveb = NULL;
- X
- X/* ngets --- get a line of input from either saved buffer or stdin */
- X
- Xchar *ngets (bp)
- Xchar *bp;
- X{
- X if (! saved)
- X return (gets (bp));
- X
- X saved = 0;
- X bp = saveb;
- X saveb = NULL;
- X return (bp);
- X}
- X
- X/* ungets --- put a buffer back on the input, so to speak */
- X
- Xvoid ungets (bp)
- Xchar *bp;
- X{
- X saved = 1;
- X saveb = bp;
- X line--;
- X}
- END_OF_cfc/cfc.c
- if test 39729 -ne `wc -c <cfc/cfc.c`; then
- echo shar: \"cfc/cfc.c\" unpacked with wrong size!
- fi
- chmod +x cfc/cfc.c
- # end of overwriting check
- fi
- echo shar: End of archive 6 \(of 6\).
- cp /dev/null ark6isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Bruce G. Barnett barnett@crd.ge.com uunet!crdgw1!barnett
-