home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2848 < prev    next >
Internet Message Format  |  1991-02-23  |  43KB

  1. From: barnett@grymoire.crd.ge.com (Bruce Barnett)
  2. Newsgroups: alt.sources
  3. Subject: Ease 3.0: High Level Language for Sendmail  (Part 6 of 6)
  4. Message-ID: <BARNETT.91Feb23021920@grymoire.crd.ge.com>
  5. Date: 23 Feb 91 07:19:20 GMT
  6.  
  7. #! /bin/sh
  8. # This is a shell archive.  Remove anything before this line, then unpack
  9. # it by saving it into a file and typing "sh file".  To overwrite existing
  10. # files, type "sh file -c".  You can also feed this as standard input via
  11. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  12. # will see the following message at the end:
  13. #        "End of archive 6 (of 6)."
  14. # Contents:  cfc/cfc.c
  15. # Wrapped by barnett@grymoire on Sat Feb 23 01:13:56 1991
  16. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  17. if test -f cfc/cfc.c -a "${1}" != "-c" ; then 
  18.   echo shar: Will not over-write existing file \"cfc/cfc.c\"
  19. else
  20. echo shar: Extracting \"cfc/cfc.c\" \(39729 characters\)
  21. sed "s/^X//" >cfc/cfc.c <<'END_OF_cfc/cfc.c'
  22. X#ifndef lint
  23. 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 $";
  24. X#endif
  25. X
  26. X/*
  27. X * $Log: cfc.c,v $
  28. X * Revision 3.0  1991/02/22  19:33:07  barnett
  29. X * Many enhancements for IDA and HP sendmail.cf files
  30. X *
  31. X * Revision 2.2  1991/02/21  19:19:34  barnett
  32. X * Fixed several bugs:
  33. X *     Multiple ifsets on one line
  34. X *     Better handling of # in comments
  35. X *     Support for escaping a '* and /' in a comment field
  36. X *
  37. X * Revision 2.1  1990/01/30  11:38:10  jeff
  38. X * Enhancements by Bruce Barnett 89/1/23:
  39. X *    - Added some enhancements for SunOS 4.0 and Ultrix 3.0
  40. X *    - And a log of unusual grammar constructs
  41. X *
  42. X * Revision 2.0  88/06/15  15:16:48  root
  43. X * Baseline release for net posting. ADR.
  44. X * 
  45. X * Revision 1.6  88/06/10  13:45:16  root
  46. X * Fix originally from Raymond A. Schnitzler (ras@sabre.bellcore.com) to
  47. X * add the (undocumented) 'P' option which sets the Postmaster address for
  48. X * receiving cc's of bad mail. ADR.
  49. X * 
  50. X * Revision 1.5  88/01/21  16:18:13  root
  51. X * Eliminated Rutgers-ism, linted, smartened Mailer Argv handling. ADR.
  52. X * 
  53. X * Revision 1.4  88/01/21  15:57:52  root
  54. X * Added the 'y' factor; missed it last time. ADR.
  55. X * 
  56. X * Revision 1.3  87/04/08  10:23:02  root
  57. X * Small bug fixes, compatibility option added, also warnings for
  58. X * unrecognized flags and options. ADR.
  59. X * 
  60. X * Revision 1.2  87/02/18  15:26:39  root
  61. X * Fix to recognize multidigit ruleset numbers in $> (calls) in RHS. ADR.
  62. X * 
  63. X * Revision 1.1  87/02/16  15:25:00  arnold
  64. X * Initial revision
  65. X * 
  66. X * Revision 1.1  87/02/16  15:25:00  arnold
  67. X * Initial revision
  68. X * 
  69. X */
  70. X
  71. X/*
  72. X * cfc.c
  73. X *
  74. X * Sendmail cf file compiler.
  75. X * Reads a raw sendmail.cf file and produces ease source.
  76. X *
  77. X * There are very few comments in this source. You will need both the
  78. X * "Sendmail Installation and Operation Guide" and the paper on Ease
  79. X * to really understand this.
  80. X *
  81. X * Arnold Robbins
  82. X * Emory University Computing Center
  83. X * 2/87
  84. X */
  85. X
  86. X#include <stdio.h>
  87. X#include <ctype.h>
  88. X
  89. Xchar buffer[BUFSIZ];
  90. Xint line = 0;
  91. Xint inruleset = 0;
  92. X
  93. Xextern char *macro ();        /* convert sendmail to ease macro names */
  94. Xextern char *mflags ();        /* convert sendmail to ease mailer flag names */
  95. Xextern char *optionname ();    /* convert sendmail to ease option names */
  96. Xextern char *delivoption ();    /* delivery options */
  97. Xextern char *handle_option ();    /* handling options */
  98. X
  99. Xextern char *ngets ();        /* buffered gets () routine */
  100. Xextern void ungets ();        /* put a buffer back for getting */
  101. X
  102. X#define endruleset()    if (inruleset) { inruleset = 0; printf ("\t}\n"); }
  103. X
  104. Xint compat = 0;            /* complain about new 4.3 options & flags */
  105. Xint undoc = 0;            /* complain about undocumented options, flags */
  106. Xint ida = 0;            /* IDA sendmail options  */
  107. Xint sunos  = 0;            /* Special parsing for SunOS - bgb */
  108. Xint DECos  = 0;            /* Special parsing for Ultrix - bgb */
  109. X                /* NOTE: can't use 'ultrix' cause of cpp */
  110. Xint hpos = 0;            /* HP/UX */
  111. X
  112. Xchar *classes = 0;            /* list of classes defined */
  113. Xmain (argc, argv)
  114. Xint argc;
  115. Xchar **argv;
  116. X{
  117. X    extern int getopt ();
  118. X    extern int optind;
  119. X    extern char *optarg;
  120. X    int i,c;
  121. X
  122. X    while ((c = getopt (argc, argv, "icdhusC:")) != EOF) {
  123. X        switch (c) {
  124. X        case 'c':
  125. X            compat = 1;
  126. X            break;
  127. X        case 'u':
  128. X            undoc = 1;
  129. X            break;
  130. X        case 's':
  131. X            sunos = 1;
  132. X            break;
  133. X        case 'd':
  134. X            DECos = 1;
  135. X            break;
  136. X        case 'i':
  137. X            ida = 1;
  138. X            break;
  139. X        case 'h':
  140. X            hpos = 1;
  141. X            break;
  142. X            case 'C':
  143. X            classes = optarg;
  144. X            break;
  145. X        case '?':
  146. X        default:
  147. X            fprintf (stderr, "usage: %s [ -[ids] ] [ -c ] [ -u ] [-C classes ]\n", argv[0]);
  148. X            break;
  149. X        }
  150. X    }
  151. X
  152. X    if (optind < argc)
  153. X        fprintf (stderr,
  154. X            "warning: ignoring non-flag command line arguments\n");
  155. X
  156. X    printf ("/***********************************************************/\n");
  157. X    printf ("/* This ease file generated by cfc version $Revision: 3.0 $*/\n");
  158. X    printf ("/* automatically from a sendmail.cf file                   */\n");
  159. X    printf ("/* It may need to be edited before feeding to ease.        */\n");
  160. X    printf ("/***********************************************************/\n");
  161. X    /* let's generate something that might work */
  162. X    printf ("bind \n");
  163. X    for (i=0;i<=29;i++) 
  164. X      printf ("\tRULESET_%d = ruleset %d;\n",i,i);
  165. X    /* SunOS uses ruleset 30. Other sendmails only support S0 to S29 */
  166. X    if (sunos)
  167. X      printf ("\tRULESET_30 = ruleset 30;\n");    
  168. X
  169. X    /*
  170. X     * For perfection, everything but the comment and rule cases
  171. X     * should do an endruleset (), but practically speaking, it is
  172. X     * usually only the mailer new ruleset definitions that end a
  173. X     * previous ruleset. Occasionally a macro, too.
  174. X     * Also class definitions - BGB
  175. X     */
  176. X
  177. X    while (ngets (buffer) != NULL)
  178. X    {
  179. X        line++;
  180. X        switch (buffer[0]) {
  181. X        case '#':
  182. X            comment ();
  183. X            continue;    /* skip code to end ruleset */
  184. X        case 'S':
  185. X            endruleset ();
  186. X            ruleset ();
  187. X            continue;    /* skip code to end ruleset */
  188. X        case 'R':
  189. X            rule ();
  190. X            continue;    /* skip code to end ruleset */
  191. X        case 'D':
  192. X            endruleset ();
  193. X            def ();
  194. X            break;
  195. X        case 'C':
  196. X            endruleset ();
  197. X            class ();
  198. X            break;
  199. X        case 'F':
  200. X            endruleset ();
  201. X            fileclass ();
  202. X            break;
  203. X        case 'M':
  204. X            endruleset ();
  205. X            mailer ();
  206. X            break;
  207. X        case 'H':
  208. X            header ();
  209. X            break;
  210. X        case 'O':
  211. X            option ();
  212. X            break;
  213. X        case 'T':
  214. X            trusted ();
  215. X            break;
  216. X        case 'P':
  217. X            precedence ();
  218. X            break;
  219. X        default:
  220. X            other ();
  221. X            continue;    /* skip code to end ruleset */
  222. X        }
  223. X        endruleset ();
  224. X    }
  225. X    endruleset ();        /* just in case */
  226. X    exit (0);
  227. X    /*NOTREACHED*/
  228. X}
  229. X
  230. X/* comment --- produce a comment */
  231. X
  232. Xcomment ()
  233. X{
  234. X    static char format[] = "/* %s */\n";
  235. X    register int i = strlen (buffer) - 1;
  236. X    register int j;
  237. X    /* try to be semi-intelligent about comments */
  238. X
  239. X    /* if a blank line, keep as a blank line */
  240. X    if (buffer[1] == '\0')
  241. X        printf ("\n");
  242. X    else { /* non-blank comment */
  243. X        j=1;
  244. X        printf("/*");
  245. X        /* print ######## as /********* */
  246. X        while (buffer[j] == '#') {
  247. X        j++;
  248. X        printf("*");
  249. X        }
  250. X        /* print the rest of the line */
  251. X        while (buffer[j] != '\0') {
  252. X        switch (buffer[j]) {
  253. X          case '#':
  254. X            /* convert ### to *** */
  255. X            if (buffer[j+1] == '\0') {
  256. X            printf("*");
  257. X            } else if (buffer[j+1] == '#') /* a string of #### */
  258. X              while (buffer[j] == '#' && buffer[j+1] != '\0') {
  259. X              printf("*");
  260. X              j++;
  261. X              }
  262. X            else printf("#");
  263. X            break;
  264. X          case '*':
  265. X            if (buffer[j+1] == '/') { 
  266. X            printf("*\\/");
  267. X            j++;
  268. X            } else printf("*");
  269. X            break;
  270. X          default:
  271. X            printf("%c", buffer[j]);
  272. X            break;
  273. X        }
  274. X        j++;
  275. X        } /* end while */
  276. X        if ( buffer[j-2] == '#' && buffer[j-1] == '#')
  277. X          printf("*/\n");
  278. X        else if ( buffer[j-2] != '#' && buffer[j-1] == '#')
  279. X          printf("*/\n");
  280. X        else if ( buffer[j-1] == ' ' || buffer[j-1] == '\t')
  281. X          printf("*/\n");
  282. X        else 
  283. X          printf(" */\n");
  284. X    } /* end of non-blank */
  285. X    }
  286. X
  287. X/* ruleset --- name a ruleset */
  288. X
  289. Xruleset ()
  290. X{
  291. X    static int first = 1;
  292. X    register char *cp = buffer + 1;
  293. X    int i;
  294. X
  295. X    if (first)
  296. X    {
  297. X        first = 0;
  298. X        printf ("\n/* These are sample field definitons (cfc) */\n");
  299. X        printf ("\nfield\n\tzero_or_more : match (0*);\n");
  300. X        printf ("\tone_or_more : match (1*);\n");
  301. X        printf ("\texactly_one : match (1);\n");
  302. X        if (classes && *classes ) {
  303. X            printf("\t/* defining classes %s */\n",classes);
  304. X            for (i=0;*(classes+i);i++) {
  305. X            printf ("\tany_in_%c : match (1) in %c;\n",*(classes+i),*(classes+i));
  306. X            printf ("\tany_not_in_%c : match (0) in %c;\n",*(classes+i),*(classes+i));
  307. X            }
  308. X        }
  309. X        /* let's make the default configuration nicer for SunOS - bgb */
  310. X        if (DECos || ida  || hpos ) {
  311. X            printf ("\tany_in_myhostname : match (1) in c_myname;\n");
  312. X        }
  313. X        if (sunos) {
  314. X/*            printf ("\tany_in_V : match (1) in V;\n");
  315. X            printf ("\tany_not_in_V : match (0) in V;\n"); */
  316. X            printf ("/*\tany_in_map_? : match (1) map ?;\t*/\n");
  317. X            printf ("/*\tany_not_in_map_? : match (0) map ?;\t*/\n");
  318. X            printf ("\tany_in_etc_hosts : match  host;\n");
  319. X            printf ("\tany_in_mydomainname : match (1) in c_mydomain;\n");
  320. X            printf ("\tany_in_myhostname : match (1) in c_myname;\n");
  321. X        } 
  322. X    }
  323. X
  324. X    printf ("ruleset\n\tRULESET_");
  325. X    while (cp && *cp && ! isspace (*cp))
  326. X    {
  327. X        putchar (*cp);
  328. X        cp++;
  329. X    }
  330. X
  331. X    printf (" {");
  332. X    if (*cp)
  333. X        printf ("\t/* %s */", cp);
  334. X    putchar ('\n');
  335. X    inruleset++;
  336. X}
  337. X
  338. X/* rule --- print out a rule */
  339. X
  340. Xrule ()
  341. X{
  342. X    register char *cp = buffer + 1;
  343. X    register char *cp2;
  344. X    register int com = 0;
  345. X
  346. X    /* first, split it up into LHS, RHS, COMMENT */
  347. X
  348. X    while (cp && *cp && *cp != '\t')
  349. X        cp++;
  350. X    if (!*cp) {
  351. X        fprintf(stderr,
  352. X            "Unexpected EOL when expecting right hand side of rule\n");
  353. X        lhs(buffer+1);
  354. X        printf("\n\tMissingRightHandSide();\n");
  355. X        return;
  356. X    }
  357. X    *cp = '\0';
  358. X
  359. X    cp++;
  360. X    while (cp && *cp && *cp == '\t')
  361. X        cp++;
  362. X    cp2 = cp;
  363. X    while (cp && *cp && *cp != '\t')
  364. X        cp++;
  365. X    if (*cp == '\t' && cp[1])
  366. X    {
  367. X        *cp = '\0';
  368. X        com++;
  369. X        cp++;
  370. X        while (cp && *cp && *cp == '\t')
  371. X            cp++;
  372. X    }
  373. X
  374. X    /* now print */
  375. X    lhs (buffer + 1);    /* left hand side */
  376. X    if (com)
  377. X        printf ("\t/* %s */", cp);
  378. X    putchar ('\n');
  379. X    rhs (cp2);        /* right hand side */
  380. X}
  381. X
  382. X/* lhs --- left hand side of a production */
  383. X
  384. Xlhs (text)
  385. Xchar *text;
  386. X{
  387. X    register char *cp = text;
  388. X    register int conditional = 0;
  389. X    register int quoting = 0;
  390. X    register int open = 0;
  391. X    int    ifset = 0;
  392. X
  393. X    printf ("\tif (");
  394. X    for (; *cp; cp++)
  395. X    {
  396. X        switch (*cp) {
  397. X        case '$':
  398. X            if (quoting)
  399. X            {
  400. X                quoting = 0;
  401. X                putchar ('"');
  402. X            }
  403. X            switch (*++cp) {
  404. X            case '*':
  405. X                printf (" zero_or_more ");
  406. X                break;
  407. X            case '+':
  408. X                printf (" one_or_more ");
  409. X                break;
  410. X            case '-':
  411. X                printf (" exactly_one ");
  412. X                break;
  413. X            case '=':
  414. X                switch(*++cp) {
  415. X                  case 'w':
  416. X                    if (sunos || ida || DECos ) {
  417. X                    printf (" any_in_myhostname ");
  418. X                    break;
  419. X                    } /* else fall through */
  420. X                  case 'm':
  421. X                    if (sunos ) {
  422. X                    printf (" any_in_mydomainname ");
  423. X                    break;
  424. X                    } /* else fall through */
  425. X                    default :
  426. X                    printf (" any_in_%c ", *cp);
  427. X                  }
  428. X                break;
  429. X                case '%' :
  430. X                   /* YP map for SunOS */
  431. X                   if ((cp+1) && sunos && (*(cp +1) == 'y') ) {
  432. X                   printf (" any_in_etc_hosts"); ++cp;
  433. X                   } else {
  434. X                   printf (" any_in_map_%c", *++cp);
  435. X                   }
  436. X                   break;
  437. X            case '~':
  438. X                printf (" any_not_in_%c ", *++cp);
  439. X                break;
  440. X            case '?':
  441. X                printf (" ifset (%s, ", macro (*++cp));
  442. X                conditional++;ifset++;
  443. X                break;
  444. X            case '|':
  445. X                if ( ! conditional) die("lhs - $| without $?");
  446. X                if ( ifset) {
  447. X                    printf("\", \"");
  448. X                } else {
  449. X                    fprintf(stderr,"Got $| when not in ifset\n");
  450. X                    putchar (',');
  451. X                }
  452. X                break;
  453. X            case '{':
  454. X                printf("ypalias (");    /* Ultrix */
  455. X                open++;
  456. X                break;
  457. X            case '"':
  458. X                printf("yppasswd (");    /* Ultrix */
  459. X                open++;
  460. X                break;
  461. X            case '.':
  462. X                putchar (')');
  463. X                conditional--;ifset--;
  464. X                break;
  465. X            case '#':
  466. X                /* IDA does something strange with this */
  467. X                printf("resolved(");
  468. X                open++;
  469. X                break;
  470. X            case '1':
  471. X            case '2':
  472. X            case '3':
  473. X            case '4':
  474. X            case '5':
  475. X            case '6':
  476. X            case '7':
  477. X            case '8':
  478. X            case '9':
  479. X                printf ("$%c", *cp);
  480. X                break;
  481. X            default:
  482. X                if (quoting)
  483. X                    printf ("${%s}", macro (*cp));
  484. X                else
  485. X                    printf ("$%s", macro (*cp));
  486. X                break;
  487. X            }
  488. X            break;
  489. X        default:
  490. X            if (ispunct (*cp))
  491. X            {
  492. X                if (quoting)    /* end a literal */
  493. X                {
  494. X                    quoting = 0;
  495. X                    putchar ('"');
  496. X                }
  497. X                /* else
  498. X                    do nothing */
  499. X            }
  500. X            else
  501. X            {
  502. X                    /* start a literal - but ignore the first space  */
  503. X                if (*cp != ' ' && ! quoting)    
  504. X                {
  505. X                    quoting = 1;
  506. X                    putchar ('"');
  507. X                }
  508. X                /* else
  509. X                    do nothing */
  510. X            }
  511. X            putchar (*cp);    /* print the character */
  512. X            break;
  513. X        }
  514. X    }
  515. X    if (quoting)
  516. X        putchar ('"');
  517. X    while (open--)
  518. X        putchar (')');
  519. X    if (conditional)
  520. X        die ("lhs");
  521. X    printf (")");
  522. X}
  523. X
  524. X/* rhs --- right hand side of a production */
  525. X
  526. Xrhs (text)
  527. Xchar *text;
  528. X{
  529. X    register char *cp = text;
  530. X    char *index ();
  531. X    char *cp1;
  532. X    register int open = 0;
  533. X    register int conditional = 0;    /* true if in an ifset condition */
  534. X    register int quoting = 0;    /* true if in a string */
  535. X    register int ifset = 0;    /* true if in ifset(), like quoting */
  536. X    register int needconcat = 0;    /* true if an $? on line (lookahead) */
  537. X    register int didconcat = 0;    /* true if did the concat()    */
  538. X    register int indbm = 0;    /* true if in IDA $( $) construct */
  539. X    register int inalias = 0;    /* true if in IDA $(@ $) construct */
  540. X    int    canon = 0;
  541. X    int    diddefault = 0;
  542. X
  543. X    printf ("\t\t");
  544. X
  545. X    /* Need to handle this line */
  546. X    /* R$+<@$=S>    $:$1<@$2>$?R<$R>$.    */
  547. X    for(cp1=cp;*cp1;cp1++) {
  548. X        if (*cp1 == '$' && (cp1+1) && *(cp1+1)== '?')
  549. X          needconcat = 1;    /* there is an ifset on this line */
  550. X    }
  551. X    if (*cp == '$' && index ("#@:", cp[1]) != NULL)
  552. X        ;    /* not the default */
  553. X    else
  554. X    {
  555. X        printf ("retry (");
  556. X        open++;
  557. X    }
  558. X
  559. X    for (; *cp; cp++)
  560. X      {
  561. X          switch (*cp) {
  562. X        case '$':
  563. X          if (quoting && ! ifset )
  564. X            {
  565. X            quoting = 0;
  566. X            putchar ('"');
  567. X            }
  568. X          switch (*++cp) {
  569. X            case '>':
  570. X              printf ("RULESET_");
  571. X              for (cp++; cp && *cp && isdigit (*cp); cp++)
  572. X            putchar (*cp);
  573. X              cp--;
  574. X              printf (" (");
  575. X              open++;
  576. X              break;
  577. X            case '[':
  578. X              if (quoting) {
  579. X              putchar('"');
  580. X              quoting--;
  581. X              }
  582. X              printf (" canon (");
  583. X              open++; canon++;
  584. X              break;
  585. X            case ']':
  586. X              putchar (')');
  587. X              open--;
  588. X              if (diddefault) {
  589. X              putchar (')');
  590. X              diddefault--;
  591. X              }
  592. X              break;
  593. X            case '{':
  594. X              printf ("ypmap (%s, ", macro (*++cp)); /* sunos */
  595. X              open++;
  596. X              break;
  597. X            case '}':
  598. X              putchar (')');
  599. X              open--;
  600. X              break;
  601. X            case '<':
  602. X              printf ("program (%s, ", macro (*++cp)); /* HP/UX */
  603. X              open++;
  604. X              break;
  605. X            case '?':
  606. X              if (didconcat) {
  607. X              printf ("\",");
  608. X              needconcat = 0; /* don't need this */
  609. X              }
  610. X              printf ("ifset (%s, \"", macro (*++cp));
  611. X              conditional++;
  612. X              ifset++;
  613. X              quoting++;
  614. X              break;
  615. X            case '|':
  616. X              if ( ! conditional) die("rhs - $| without $?");
  617. X              if ( ifset) {
  618. X              printf("\", \"");
  619. X              } else {
  620. X              fprintf(stderr,"Got $| when not in ifset\n");
  621. X              putchar (',');
  622. X              }
  623. X              break;
  624. X            case '.':
  625. X              if (ifset && quoting ) {
  626. X              putchar('"'); quoting--;
  627. X              }
  628. X              if (! ifset ) fprintf(stderr,"Got $. while not in ifset\n");
  629. X              putchar (')');
  630. X              if (open) {
  631. X              putchar(')');
  632. X              open--;
  633. X              }
  634. X              conditional--;
  635. X              ifset--;
  636. X              break;
  637. X            case '#':
  638. X              parseresolve(cp);
  639. X              goto out;    /* string is exhausted */
  640. X              /* break; */
  641. X            case '@':
  642. X              if ( ! indbm) {
  643. X              printf ("return (");
  644. X              if (needconcat && cp+1 && cp+2 &&
  645. X                  ! ((*(cp+1) == '$') && (*(cp+2) == '?'))){ 
  646. X                  printf ("concat (\"");
  647. X                  open++;didconcat++;
  648. X              }
  649. X              open++;
  650. X              } else {
  651. X              printf("\", \"");
  652. X              }
  653. X              break;
  654. X            case ':':
  655. X              if ( canon ) {
  656. X              printf("default ( ");
  657. X              canon--;diddefault++;
  658. X              } else if ( indbm ) {
  659. X              printf("default ( ");
  660. X              indbm--;diddefault++;
  661. X              } else {
  662. X              printf ("next (");
  663. X              if (needconcat && cp+1 && cp+2 &&
  664. X                  ! ((*(cp+1) == '$') && (*(cp+2) == '?'))){ 
  665. X                  printf ("concat (\"");
  666. X                  open++;didconcat++;
  667. X              }
  668. X              open++;
  669. X              } 
  670. X              break;
  671. X            case '(':
  672. X              if (*(cp+1) == '@') { /* then IDA alias lookup */
  673. X              cp++;    /* point past '@' */
  674. X              printf("alias(");
  675. X              indbm++;
  676. X              open++;
  677. X              } else { /* lookup */
  678. X              printf("dbm(");
  679. X              printf("$%s, \"",macro(*cp++));
  680. X              }
  681. X              break;
  682. X            case ')':
  683. X              printf("))");
  684. X              open--;
  685. X              indbm--;
  686. X              break;
  687. X            case '&':
  688. X              printf(" eval(%s) ",macro(*(++cp)));
  689. X              break;
  690. X            case '1':
  691. X            case '2':
  692. X            case '3':
  693. X            case '4':
  694. X            case '5':
  695. X            case '6':
  696. X            case '7':
  697. X            case '8':
  698. X            case '9':
  699. X              printf ("$%c", *cp);
  700. X              break;
  701. X            default:
  702. X              if (ifset ) {
  703. X              if (quoting)
  704. X                printf ("${%s}", macro (*cp));
  705. X              else
  706. X                printf ("$%s", macro (*cp));
  707. X              } else { /* not not in ifset() */
  708. X              if (quoting)
  709. X                printf ("${%s}", macro (*cp));
  710. X              else 
  711. X                printf ("$%s", macro (*cp));
  712. X              }
  713. X              break;
  714. X          }
  715. X          break;         /* not a character that starts with a $ */
  716. X        default:
  717. X          if ( ifset  && quoting ) {
  718. X              putchar(*cp);
  719. X          } else if (ifset  && ! quoting) {
  720. X              if ( ispunct (*cp)) {
  721. X              putchar('"');quoting++;
  722. X              } 
  723. X              putchar(*cp); 
  724. X          } else {    /* not ifset */
  725. X              if (ispunct (*cp))
  726. X            {
  727. X                if (quoting )    /* end a literal */
  728. X                  {
  729. X                  quoting = 0;
  730. X                  putchar ('"');
  731. X                  }
  732. X                /* else
  733. X                   do nothing */
  734. X            } else  {
  735. X                if (*cp != ' ' && ! quoting)    /* start a literal */
  736. X                  {
  737. X                  quoting = 1;
  738. X                  putchar ('"');
  739. X                  }
  740. X                /* else
  741. X                   do nothing */
  742. X            }
  743. X              putchar (*cp);    /* print the character */
  744. X          }
  745. X          break;
  746. X          }
  747. X      } /* end of for */
  748. Xout:
  749. X    if (quoting)
  750. X        putchar ('"');
  751. X    while (open--)
  752. X        putchar (')');
  753. X    printf (";\n");
  754. X    if (conditional)
  755. X        die ("rhs - $? without $.");
  756. X}
  757. X/* parseresolve - parse this mailer/host/user mess */
  758. Xparseresolve(cp)
  759. Xchar    *cp;
  760. X{
  761. X    int quoting = 0;
  762. X    int open = 0;
  763. X    char *addrops;
  764. X    addrops = ".:;%@!=/[]?#^,<>$"; /* should be defined from input file */
  765. X    printf ("resolve (mailer (");
  766. X/*  if (strncmp (cp+1, "local", 5) == 0
  767. X    || strncmp (cp+1, "error", 5) == 0
  768. X    || strncmp (cp+1, "LOCAL", 5) == 0
  769. X    || strncmp (cp+1, "ERROR", 5) == 0)
  770. X    goto skiphost;
  771. Xloop1:
  772. X*/
  773. X    /* this is a simple parser that scans the right
  774. X       hand side of a $# rule
  775. X       The format is usually
  776. X       "$# mailer $@ host $: user" or
  777. X       "$# mailer $: user"  or
  778. X       "$# mailer $: something with a $macro"  or
  779. X       "$# $M $: user"  or
  780. X       "$# $1 "   (IDA sendmail )
  781. X       
  782. X       Note that there may be special constructs
  783. X       in the host field, i.e.
  784. X       "$1", "[$2]", "$w", or "$K".
  785. X       and in the user field. Esp. in the error mailer:
  786. X       "$1 < @$2 > $4",  or
  787. X       "Never heard of host $2 in domain $m "
  788. X       "$n" which should become -> "$m_daemon"
  789. X       */
  790. X    /* pointing to '#' */
  791. X    cp++;
  792. X    /* output any character not a '$' */
  793. X    while (cp && *cp && *cp != '$' ) {
  794. X    /* skip spaces in the mailer field */
  795. X    if ( *cp != ' ' ) putchar(*cp); 
  796. X    cp++;
  797. X    }
  798. X    if (!cp || !*cp ) goto out;
  799. X    /* currently pointing to a "$" */
  800. X    /* we may now be pointing to:
  801. X       $@ - the host name
  802. X       $: - the user
  803. X       or a macro
  804. X       or nothing?! (*cp == 0);
  805. X       /* don't look at the '$' */
  806. X    cp++;
  807. X    if (!cp || !*cp ) goto out;
  808. X    if (*cp  == ':') goto parseuser;
  809. X    if (*cp != '@' ) {
  810. X    /* must be a macro name */
  811. X    printf ("$%s",macro(*cp++));
  812. X    /* now skip to the $@ */
  813. X    if (!cp || !*cp ) goto out;
  814. X    while (cp && *cp && *cp == ' ') cp++;
  815. X    if (!cp || !*cp ) goto out;
  816. X    if (*cp == '$') cp++; 
  817. X    else 
  818. X      fprintf(stderr,
  819. X          "Error: found %c when expecting a '$' on line %d\n",
  820. X          *cp,line);
  821. X    if (*cp == ':') goto parseuser;
  822. X    if (*cp == '@') cp++;
  823. X    else 
  824. X      fprintf(stderr,
  825. X          "Error: found %c when expecting a '@' on line %d\n",
  826. X          *cp,line);
  827. X    } else {
  828. X    /* I did see the '@' of the $@ */
  829. X    cp++;
  830. X    }
  831. X    /* print host name ($@host ) */
  832. X    printf ("),\n\t\t\t\thost (");
  833. X    for (;cp && *cp;cp++) {
  834. X    if (*cp != '$') { 
  835. X        putchar (*cp);
  836. X    } else {
  837. X        /* it might be the $: */
  838. X        if (!*(cp+1)) goto out;
  839. X        if ( *(cp+1) == ':') {
  840. X        cp++; /* parseuser expects ':' */
  841. X        goto parseuser;
  842. X        } else {
  843. X        putchar(*cp++); /* print '$' */
  844. X        printf("%s", macro(*cp)); /* and next */
  845. X        }
  846. X    }
  847. X    }
  848. X  parseuser:
  849. X    printf ("),\n\t\t\t\tuser (");
  850. X    /* *cp == ':', now look for user = $n */
  851. X    /* maybe *cp == 0 */
  852. X    if ( !*cp ) goto out;
  853. X    if (*cp != ':' ) 
  854. X      fprintf(stderr,
  855. X          "Expected ':', found '%c' after '$' on line %d\n",*cp,line);
  856. X    /* looking at the user string */
  857. X    quoting = 0;
  858. X    for (cp++; cp && *cp; cp++) {
  859. X    if (quoting ) {
  860. X/*        if (isalnum(*cp) || isspace(*cp)) { */
  861. X        if (*cp == '"') {
  862. X        printf("\\\"");    /* print "\" */
  863. X        quoting++;
  864. X        } else if (*cp == '\\') {
  865. X        printf("\\");    /* print "\" and the next character */
  866. X        putchar(*++cp);
  867. X        } else if (!index(addrops,*cp))  {    
  868. X        /* not one of those address characters */
  869. X        putchar (*cp);
  870. X        } else { /* maybe it's a dollar sign? */
  871. X        quoting=0;
  872. X        printf("\" %c",*cp);
  873. X        if (*cp == '$') {
  874. X            cp++;    /* This may not be used at all - but it can't hurt */
  875. X            if (*cp == '>' ) { /* IDA sendmail */
  876. X            cp++;
  877. X            printf(" RULESET_");
  878. X            while (cp && *cp && *cp >= '0' && *cp <= '9') putchar(*cp++);
  879. X            printf("(");
  880. X            open++;
  881. X            } else {
  882. X            printf("%s",macro(*cp));
  883. X            }
  884. X        }
  885. X        }
  886. X    } else {    /* not quoting */
  887. X        if ( *cp == '$' ) {
  888. X        cp++;
  889. X        if (*cp == '>' ) { /* IDA sendmail */
  890. X            cp++;
  891. X            printf("retry (RULESET_");
  892. X            while (cp && *cp && *cp >= '0' && *cp <= '9') putchar(*cp++);
  893. X            printf("("); open++;
  894. X            open++;
  895. X        } else {
  896. X            putchar ('$'); /* print $ */
  897. X            printf("%s",macro(*cp)); /* and macro */
  898. X        }
  899. X        } else if (*cp && (index (addrops,*cp))) {
  900. X        putchar(*cp);
  901. X        } else if (*cp == '"') {
  902. X        printf("\"\\\"");quoting++;    /* print "\" */
  903. X        } else {
  904. X        quoting = 1;
  905. X        printf(" \"%c",*cp);
  906. X        } 
  907. X    } /* end of quoting/not quoting */
  908. X    }
  909. X    if (quoting) printf("\"");
  910. X  out:
  911. X    while (open--) printf(")");
  912. X    printf ("))");
  913. X} /* end parseresolve () */
  914. X/* def --- define a macro */
  915. X
  916. Xdef ()
  917. X{
  918. X    register char *mac = buffer + 1, *value = buffer + 2;
  919. X    register int conditional = 0;
  920. X    register int concat = 0;
  921. X    register int quote = 0;
  922. X    register int ifset = 0;
  923. X    
  924. X
  925. X    printf ("macro\n\t%s = ", macro (*mac));
  926. X/*    fprintf(stderr,"mac=%c, value=%s\n",*mac,value); */
  927. X
  928. X/* This is tricky, we want the form:
  929. X *
  930. X *    Dq$g$?x$x$.
  931. X * to become
  932. X *  macro
  933. X *       m_defaddr = concat ("${m_sreladdr}", ifset (m_sname," (${m_sname})"));
  934. X * and
  935. X *      Dq$?x$x $.<$g>
  936. X * to become
  937. X *  macro
  938. X *       m_defaddr = concat (ifset (m_sname," (${m_sname})"),"<${m_sreladdr}>" );
  939. X *
  940. X * One problem is the form 
  941. X *    Dq$?x$x <$g>$|$g$.
  942. X *
  943. X *
  944. X */
  945. X    concat = 0;
  946. X    quote = 0;
  947. X    conditional = 0;
  948. X    ifset = 0;
  949. X    if (! *value ) printf("\"\""); /* unusual error - just print " and let
  950. X                           the end of the loop after the while 
  951. X                           clean it up */
  952. X    while (*value)
  953. X    {
  954. X        switch (*value) {
  955. X        case '$':
  956. X            switch (*++value) {
  957. X            /* $:$?E$1%$2.dnet<@$E.LOCAL>$3$|$1<@$2.dnet>$3$. 
  958. X               Dq$?x$x <$g>$|$g$.
  959. X               Dq$?x$!x <$g>$|$g$.
  960. X               */
  961. X            case '?':
  962. X                    /* Another special case %$&*! 
  963. X                     * if the start of the string is $?, 
  964. X                 * but the end is NOT $., then we need a concat
  965. X                 */
  966. X                    if (*(value+strlen(value)-1) == '.' &&
  967. X                        *(value+strlen(value)-2) == '$') {
  968. X                    /* just use ifset with no concat */
  969. X                    printf ("ifset (%s, ", macro (*++value));
  970. X                    conditional++;ifset++;
  971. X                    /* Still need a quote character,
  972. X                       next characters might be a $!x */
  973. X                    if ((*(value+1) == '$') && (*(value+2) == '!')) {
  974. X                    value++;value++;
  975. X                    printf("\"${quote(%s)} ",macro(*++value));
  976. X                    quote++;
  977. X                    } else {
  978. X                    printf("\"");quote++;
  979. X                    }
  980. X                } else {
  981. X                    printf ("concat( ifset (%s, \"", macro (*++value));
  982. X                    conditional++;quote++;concat++;ifset++;
  983. X                }
  984. X                break;
  985. X            case '|':
  986. X                if ( ! conditional) die("def - $| without $?");
  987. X                if ( ifset) {
  988. X                    printf("\", \"");
  989. X                } else {
  990. X                    fprintf(stderr,"Got $| when not in ifset\n");
  991. X                    putchar (',');
  992. X                }
  993. X                break;
  994. X            case '.':
  995. X                if (quote) {
  996. X                    putchar('"');quote--;
  997. X                }
  998. X                putchar (')');
  999. X                conditional--;ifset--;
  1000. X                /* not EOL, must be in concat(ifset( ,) */
  1001. X                if (*(value+1)) putchar(','); 
  1002. X                break;
  1003. X                  case '!':    /* IDA sendmail  - this code never gets executed */
  1004. X                printf("quote("); concat++;
  1005. X                break;
  1006. X                default:
  1007. X            /* see if *(value+1) == '$' and *(value+2) == '?' */
  1008. X                if (!concat && (strlen(value)>2) 
  1009. X                    && (*(value+1) == '$')
  1010. X                    && (*(value+2) == '?')) {
  1011. X                    printf ("concat (\"${%s}\", ", macro (*value));
  1012. X                    /* I'm gonna need a concat */
  1013. X                    concat++;
  1014. X                } else {
  1015. X                    if (!quote) {
  1016. X                    printf("\"${%s}", macro (*value));
  1017. X                    quote++;
  1018. X                    } else {
  1019. X                    printf ("${%s}", macro (*value));
  1020. X                    }
  1021. X                }
  1022. X                break;
  1023. X            }
  1024. X            break;
  1025. X            case '"' :
  1026. X                if (quote) {
  1027. X                printf ("\\\"");
  1028. X            } else {
  1029. X                printf("\"\\\"");
  1030. X                quote++;
  1031. X            }
  1032. X            break;
  1033. X        default:
  1034. X            if ( ! quote ) {
  1035. X                putchar('"');
  1036. X                quote++;
  1037. X            }
  1038. X            putchar (*value);
  1039. X            break;
  1040. X        }
  1041. X        value++;
  1042. X    }
  1043. X    if ( quote ) putchar('"');
  1044. X    if (concat) {
  1045. X        putchar (')');
  1046. X        concat--;
  1047. X    }
  1048. X    printf (";\n");
  1049. X    if (conditional)
  1050. X        die ("def - $? without $.");
  1051. X}
  1052. X
  1053. X/* class --- define a class list */
  1054. X
  1055. Xclass ()
  1056. X{
  1057. X    register char *name = buffer + 1, *value = buffer + 2;
  1058. X    int  havepunct;
  1059. X    char *s;
  1060. X
  1061. X
  1062. X    printf ("class\n\t");
  1063. X      switch (name[0]) {
  1064. X        case 'w' :     printf("c_myname"); break;
  1065. X        case 'm' :     if (sunos) { printf("c_mydomain"); break; }
  1066. X          /* fall through if not SunOS */
  1067. X        default:    printf("%c",name[0]);
  1068. X      }
  1069. X
  1070. X    printf (" = { ");
  1071. X
  1072. X    while (value && *value && isspace (*value))
  1073. X        value++;
  1074. X
  1075. X    /* a class may be a series of punctuation characters e.g. IDA */
  1076. X    /* also watch for spaces on the end of a line and avoid ',)' */
  1077. X
  1078. X    while (value && *value)
  1079. X    {
  1080. X        /* get first field */
  1081. X        /* look for first space or EOL */
  1082. X        for (s=value,havepunct=0;*s && ! isspace (*s);s++)
  1083. X          if (ispunct(*s)) havepunct = 1;
  1084. X
  1085. X        /* field is from *value to *s  
  1086. X           if there is a punctuation char, havepunt == 1 */
  1087. X        if (havepunct) putchar('"');
  1088. X        while (value < s ) {
  1089. X        if (*value == '"') putchar('\\');     /* escape quotes */
  1090. X        if (*value == '$' ) printf ("${%s}", macro (*++value));
  1091. X        else putchar(*value);
  1092. X        value++;
  1093. X        }
  1094. X        if (havepunct) putchar('"');
  1095. X        /* if not EOL, put a comma there 
  1096. X           but watch out for extra spaces..... 
  1097. X
  1098. X           so scan over spaces, then look at the next character.
  1099. X           If not EOL, print ", ". */
  1100. X
  1101. X           while (value && *value && isspace(*value)) value++;
  1102. X           if (*value && !isspace(*value)) printf (", ");
  1103. X    }
  1104. X    printf (" };\n");
  1105. X}
  1106. X
  1107. X/* fileclass --- define a class that is to be read from a file */
  1108. X
  1109. Xfileclass ()
  1110. X{
  1111. X    register char *name = buffer + 1, *value = buffer + 2;
  1112. X
  1113. X    printf ("class\n\t%c = readclass (\"", *name);
  1114. X    for (; *value && !isspace (*value); value++)
  1115. X        putchar (*value);
  1116. X    putchar ('"');
  1117. X    while (value && *value && isspace (*value))
  1118. X        value++;
  1119. X    if (*value)
  1120. X        printf (", \"%s\"", value);
  1121. X    printf (");\n");
  1122. X}
  1123. X
  1124. X/* mailer --- convert a mailer specification */
  1125. X
  1126. Xmailer ()
  1127. X{
  1128. X    register char *cp = buffer + 1;
  1129. X
  1130. X    printf ("mailer\n\t");
  1131. X    for (; *cp != ','; cp++)
  1132. X        putchar (*cp);
  1133. X    cp++;
  1134. X    printf (" {\n");    /* just did mailer name */
  1135. X
  1136. X#define skipname()    cp++; while (cp && *cp && *cp != '=') cp++; cp++
  1137. X#define value()        for (; cp && *cp && *cp != ','; cp++) putchar (*cp); cp++
  1138. X
  1139. Xloop:
  1140. X    while (cp && *cp && isspace (*cp))
  1141. X        cp++;
  1142. X
  1143. X    printf ("\t\t");
  1144. X    switch (*cp) {
  1145. X    case 'A':
  1146. X        skipname ();
  1147. X        printf ("Argv = \"");
  1148. X        for (; *cp && *cp != ','; cp++)
  1149. X        {
  1150. X            if (*cp == '$')    /* XXX: assume no conditionals */
  1151. X                printf ("${%s}", macro (*++cp));
  1152. X            else if (*cp == '"')
  1153. X                printf ("\\\"");
  1154. X            else
  1155. X                putchar (*cp);
  1156. X        }
  1157. X        cp++;    /* do manually what value does */
  1158. X        putchar ('"');
  1159. X        break;
  1160. X
  1161. X    case 'E':
  1162. X        skipname ();
  1163. X        printf ("Eol = \"");
  1164. X        value ();
  1165. X        putchar ('"');
  1166. X        break;
  1167. X
  1168. X    case 'F':
  1169. X        skipname ();
  1170. X        printf ("Flags = { ");
  1171. X        for (; *cp && *cp != ','; cp++)
  1172. X        {
  1173. X            printf ("%s", mflags (*cp));
  1174. X            if (cp[1] && cp[1] != ',')
  1175. X                printf (", ");
  1176. X        }
  1177. X        cp++;    /* do manually what value does */
  1178. X        printf (" }");
  1179. X        break;
  1180. X
  1181. X    case 'M':
  1182. X        skipname ();
  1183. X        printf ("Maxsize = \"");
  1184. X        value ();
  1185. X        putchar ('"');
  1186. X        break;
  1187. X
  1188. X    case 'P':
  1189. X        skipname ();
  1190. X        printf ("Path = \"");
  1191. X        value ();
  1192. X        putchar ('"');
  1193. X        break;
  1194. X
  1195. X    case 'R':
  1196. X        skipname ();
  1197. X        printf ("Recipient = RULESET_");
  1198. X        /* IDA has ruleset/ruleset */
  1199. X        for (; *cp && *cp != ',' && *cp != '/'; cp++) 
  1200. X          putchar (*cp); 
  1201. X        if (ida && cp && (*cp == '/' )) {
  1202. X            putchar (*cp++);
  1203. X            printf("RULESET_");
  1204. X            value ();
  1205. X        } else {
  1206. X            cp++ ;
  1207. X        }
  1208. X        break;
  1209. X
  1210. X    case 'S':
  1211. X        skipname ();
  1212. X        printf ("Sender = RULESET_");
  1213. X        /* IDA has ruleset/ruleset */
  1214. X        for (; *cp && *cp != ',' && *cp != '/'; cp++) 
  1215. X          putchar (*cp); 
  1216. X        if (ida && cp && (*cp == '/' )) {
  1217. X            putchar (*cp++);
  1218. X            printf("RULESET_");
  1219. X            value ();
  1220. X        } else {
  1221. X            cp++ ;
  1222. X        }
  1223. X        break;
  1224. X
  1225. X    case '\0':
  1226. X        goto done;
  1227. X    }
  1228. X
  1229. X    if (cp[-1] && cp[-1] == ',')
  1230. X    {
  1231. X        printf (",\n");
  1232. X        goto loop;
  1233. X    }
  1234. X    else
  1235. X        putchar ('\n');
  1236. X
  1237. Xdone:
  1238. X    /* handle continuation lines */
  1239. X    if (ngets (buffer) != NULL)
  1240. X    {
  1241. X        line++;
  1242. X        if (buffer[0] == '\t')
  1243. X        {
  1244. X            cp = buffer;
  1245. X            goto loop;
  1246. X        }
  1247. X        else
  1248. X            ungets (buffer);
  1249. X    }
  1250. X    else
  1251. X        ungets ((char *) NULL);
  1252. X    
  1253. X    printf ("\t};\n");
  1254. X
  1255. X#undef value
  1256. X#undef skipname
  1257. X}
  1258. X
  1259. X/* header --- define sendmail headers */
  1260. X
  1261. Xheader ()
  1262. X{
  1263. X    register char *cp = buffer + 1;
  1264. X    register int flags = 0;
  1265. X    register int conditional = 0;
  1266. X    register int concat = 0;
  1267. X    register int quote = 0;
  1268. X    register int ifset = 0;
  1269. X
  1270. X    printf ("header\n\t");
  1271. X    if (*cp == '?')        /* header for mailers  with these flags */
  1272. X    {
  1273. X        flags++;
  1274. X        printf ("for (");
  1275. X        for (cp++; cp && *cp != '?'; cp++)
  1276. X        {
  1277. X            printf ("%s", mflags (*cp));
  1278. X            if (cp[1] != '?')
  1279. X                putchar (',');
  1280. X        }
  1281. X        printf (") {\n\t\t");
  1282. X        cp++;    /* skip final '?' */
  1283. X    }
  1284. X
  1285. X    printf ("define (\"");
  1286. X    for (; *cp && ! isspace (*cp); cp++)
  1287. X        putchar (*cp);
  1288. X    /* skip over any spaces */
  1289. X    while ( cp && *cp && isspace(*cp)) cp++;
  1290. X        /* but if we are now at the end of the line, we must fake
  1291. X       an entry for "" */
  1292. X    if ( cp && *cp ) printf ("\", ");  /* don't print next " yet, see if it is a concat */
  1293. X    else if (cp && ! *cp ) printf("\", \"\"");
  1294. X    else if (!cp) {
  1295. X        printf("\"");
  1296. X        fprintf(stderr,"I didn't expect this!\n");
  1297. X    }
  1298. X
  1299. X    quote = concat = conditional = ifset = 0;
  1300. Xbody:
  1301. X    while (cp && *cp)
  1302. X    {
  1303. X        switch (*cp) {
  1304. X        case '$':
  1305. X            switch (*++cp) {
  1306. X            case '?':
  1307. X                /* if we are not in a concat, then start one */
  1308. X                if ( ! concat ) {
  1309. X                printf("concat (");
  1310. X                concat++;
  1311. X                }  else { /* we are in one */
  1312. X                if (quote) {
  1313. X                    printf("\"");quote--;
  1314. X                }
  1315. X                printf("), concat (");
  1316. X                }
  1317. X                if (quote) {
  1318. X                printf("\",");quote--;
  1319. X                }
  1320. X                printf ("ifset (%s, \"", macro (*++cp));
  1321. X                conditional++; quote++;ifset++;
  1322. X                break;
  1323. X            case '|':
  1324. X                if ( ! conditional) die("header - $| without $?");
  1325. X                if ( ifset) {
  1326. X                    printf("\", \"");
  1327. X                } else {
  1328. X                    fprintf(stderr,"Got $| when not in ifset\n");
  1329. X                    putchar (',');
  1330. X                }
  1331. X                break;
  1332. X            case '.':
  1333. X                if (quote) {
  1334. X                putchar('"');quote--;
  1335. X                }
  1336. X                putchar (')');
  1337. X                conditional--;ifset--;
  1338. X                if (concat) {
  1339. X                /* this is messy - There may be more than one $? on a line */
  1340. X
  1341. X                if (cp+1) { /* if there is more on the line */
  1342. X                    printf(", ");
  1343. X                }
  1344. X                }
  1345. X                break;
  1346. X            default: /* a $<letter> */
  1347. X            /* see if *(cp+1) == '$' and *(cp+2) == '?' */
  1348. X                if (!concat && (strlen(cp)>2) 
  1349. X                && (*(cp+1) == '$')
  1350. X                && (*(cp+2) == '?')) {
  1351. X                printf ("concat (\"${%s}\", ", macro (*cp));
  1352. X                /* I'm gonna need a concat */
  1353. X                concat++;
  1354. X                } else {
  1355. X                if (!quote) {
  1356. X                    printf("\"${%s}", macro (*cp));
  1357. X                    quote++;
  1358. X                } else {
  1359. X                    printf ("${%s}", macro (*cp));
  1360. X                }
  1361. X                }
  1362. X                break;
  1363. X            }
  1364. X            break;
  1365. X            case '"' :
  1366. X            printf ("\\\"");
  1367. X            break;
  1368. X        default:
  1369. X            if ( ! quote ) {
  1370. X                putchar('"');
  1371. X                quote++;
  1372. X            }
  1373. X            putchar (*cp);
  1374. X            break;
  1375. X        }
  1376. X        cp++;
  1377. X    }
  1378. X
  1379. X    /* handle continuation lines */
  1380. X    if (ngets (buffer) != NULL)
  1381. X    {
  1382. X        line++;
  1383. X        if (buffer[0] == '\t')
  1384. X        {
  1385. X            if ( ! quote ) {
  1386. X                putchar('"');
  1387. X                quote++;
  1388. X            }
  1389. X            printf ("\\\n");
  1390. X            cp = buffer + 1;
  1391. X
  1392. X            goto body;
  1393. X        }
  1394. X        else
  1395. X            ungets (buffer);
  1396. X    }
  1397. X    else
  1398. X        ungets ((char *) NULL);
  1399. X
  1400. X    if ( quote ) {
  1401. X        putchar('"'); 
  1402. X    }
  1403. X    if (concat) {
  1404. X        putchar(')');
  1405. X        concat--;
  1406. X    }
  1407. X    printf (");\n");
  1408. X
  1409. X    if (flags)
  1410. X        printf ("\t};\n");
  1411. X
  1412. X    if (conditional)
  1413. X        die ("header translation  problem: $? without $.");
  1414. X}
  1415. X
  1416. X/* option --- translate a sendmail option to an ease option */
  1417. X
  1418. Xoption ()
  1419. X{
  1420. X    register char *name = buffer + 1, *value = buffer + 2;
  1421. X
  1422. X    printf ("options\n\t");
  1423. X    if (*name == 'd')        /* delivery */
  1424. X        printf ("o_delivery = %s;\n", delivoption (*value));
  1425. X    else if (*name == 'e')        /* handling */
  1426. X        printf ("o_handling = %s;\n", handle_option (*value));
  1427. X    else
  1428. X        printf ("%s = \"%s\";\n", optionname (*name), value);
  1429. X}
  1430. X
  1431. X/* trusted --- define the list of trusted users */
  1432. X
  1433. Xtrusted ()
  1434. X{
  1435. X    register char *cp = buffer + 1;
  1436. X
  1437. X    if ( *cp && *cp == ' ') cp++; /* skip over spaces in the begining */
  1438. X    while (cp && *cp)
  1439. X    {
  1440. X        if (isspace (*cp))
  1441. X            *cp = ',';
  1442. X        cp++;
  1443. X    }
  1444. X    printf ("trusted\n\t{ %s };\n", buffer+1);
  1445. X}
  1446. X
  1447. X/* precedence --- define the precedence of a message class */
  1448. X
  1449. Xprecedence ()
  1450. X{
  1451. X    register char *cp = buffer + 1;
  1452. X
  1453. X    printf ("precedence\n\t");
  1454. X    for (; *cp && *cp != '='; cp++)
  1455. X        putchar (*cp);
  1456. X    printf (" = %s;\n", ++cp);
  1457. X}
  1458. X
  1459. X/* other --- not a sendmail control line */
  1460. X/* it may also be a blank line           */
  1461. X
  1462. Xother ()
  1463. X{
  1464. X    printf ("%s\n", buffer);
  1465. X}
  1466. X
  1467. Xdie (routine)
  1468. Xchar *routine;
  1469. X{
  1470. X    fprintf (stderr, "%s: malformed input line %d: fatal error\n",
  1471. X            routine, line);
  1472. X    exit (1);
  1473. X}
  1474. X
  1475. X/* macro --- return name for sendmail predefined macro */
  1476. X
  1477. Xchar *macro (c)
  1478. Xchar c;
  1479. X{
  1480. X    static char buf[2] = { '\0', '\0' };
  1481. X
  1482. X    switch (c) {
  1483. X    case 'a':    /* The origination date in Arpanet format */
  1484. X        return ("m_odate");
  1485. X
  1486. X    case 'b':    /* The current date in Arpanet format */
  1487. X        return ("m_adate");
  1488. X
  1489. X    case 'c':    /* The hop count */
  1490. X        return ("m_hops");
  1491. X
  1492. X    case 'd':    /* The date in UNIX (ctime) format */
  1493. X        return ("m_udate");
  1494. X
  1495. X    case 'e':    /* The SMTP entry message */
  1496. X        return ("m_smtp");
  1497. X
  1498. X    case 'f':    /* The sender (from) address */
  1499. X        return ("m_saddr");
  1500. X
  1501. X    case 'g':    /* The sender address relative to the recipient */
  1502. X        return ("m_sreladdr");
  1503. X
  1504. X    case 'h':    /* The recipient host */
  1505. X        return ("m_rhost");
  1506. X
  1507. X    case 'i':    /* The queue id */
  1508. X        return ("m_qid");
  1509. X
  1510. X    case 'j':    /* The official domain name for this site */
  1511. X        return ("m_oname");
  1512. X
  1513. X    case 'k':    /* The official domain name for this site */
  1514. X        return ("m_uucpname");    /* IDA */
  1515. X
  1516. X    case 'l':    /* The format of the UNIX from line */
  1517. X        return ("m_ufrom");
  1518. X
  1519. X    case 'm':    /* The Domain Name (SunOS) */
  1520. X        if (sunos) {
  1521. X            return ("m_domain");
  1522. X        } else {
  1523. X            buf[0] = c;
  1524. X            return (buf);
  1525. X        }
  1526. X
  1527. X    case 'n':    /* The name of the daemon (for error messages) */
  1528. X        return ("m_daemon");
  1529. X
  1530. X    case 'o':    /* The set of "operators" in addresses */
  1531. X        return ("m_addrops");
  1532. X
  1533. X    case 'p':    /* Sendmail's pid */
  1534. X        return ("m_pid");
  1535. X
  1536. X    case 'q':    /* The default format of sender address */
  1537. X        return ("m_defaddr");
  1538. X
  1539. X    case 'r':    /* Protocol used */
  1540. X        return ("m_protocol");
  1541. X
  1542. X    case 's':    /* Sender's host name */
  1543. X        return ("m_shostname");
  1544. X
  1545. X    case 't':    /* A numeric representation of the current time */
  1546. X        return ("m_ctime");
  1547. X
  1548. X    case 'u':    /* The recipient user */
  1549. X        return ("m_ruser");
  1550. X
  1551. X    case 'v':    /* The version number of sendmail */
  1552. X        return ("m_version");
  1553. X
  1554. X    case 'w':    /* The hostname of this site */
  1555. X        return ("m_sitename");
  1556. X
  1557. X    case 'x':    /* The full name of the sender */
  1558. X        return ("m_sname");
  1559. X
  1560. X    case 'y':    /* The id of the sender's tty */
  1561. X        return ("m_stty");
  1562. X
  1563. X    case 'z':    /* The home directory of the recipient */
  1564. X        return ("m_rhdir");
  1565. X
  1566. X        case '"':    /* you can get a quote charater in some macro definitions */
  1567. X        return ("\\\"");
  1568. X    default:
  1569. X        buf[0] = c;
  1570. X        return (buf);
  1571. X    }
  1572. X}
  1573. X
  1574. X#define docompat(val)    if (compat) goto warn; else return (val)
  1575. X#define dofundoc(val)    if (undoc) \
  1576. Xfprintf (stderr, "warning: undocumented flag '%c' used on line %d\n", c, line);\
  1577. Xreturn (val)
  1578. X
  1579. X/* mflags --- convert sendmail mailer flags to ease names */
  1580. X
  1581. Xchar *mflags (c)
  1582. Xchar c;
  1583. X{
  1584. X    static char buf[2] = { '\0', '\0' };
  1585. X
  1586. X    switch (c) {
  1587. X    case 'f':    return ("f_ffrom");
  1588. X    case 'r':    return ("f_rfrom");
  1589. X    case 'S':    return ("f_noreset");
  1590. X    case 'n':    return ("f_noufrom");
  1591. X    case 'l':    return ("f_locm");
  1592. X    case 's':    return ("f_strip"); 
  1593. X    case 'm':    return ("f_mult");
  1594. X    case 'F':    return ("f_from");
  1595. X    case 'D':    return ("f_date");
  1596. X    case 'M':    return ("f_mesg");
  1597. X    case 'x':    return ("f_full");    
  1598. X    case 'P':    return ("f_return");    
  1599. X    case 'u':    return ("f_upperu");    
  1600. X    case 'h':    return ("f_upperh");    
  1601. X    case 'H':    return ("f_mail11");    /* Ultrix 3.0 */
  1602. X    case 'A':    return ("f_arpa");    
  1603. X    case 'U':     return ("f_ufrom");
  1604. X    case 'e':    return ("f_expensive");
  1605. X    case 'X':    return ("f_dot");
  1606. X    case 'L':    return ("f_llimit");    
  1607. X    case 'p':    return ("f_retsmtp");    
  1608. X    case 'I':    return ("f_smtp");    
  1609. X    case 'C':    return ("f_addrw");    
  1610. X    case 'E':    docompat ("f_escape");
  1611. X    case 'R':    dofundoc ("f_rport");
  1612. X    case 'B':    return ("f_bsmtp"); /* IDA sendmail */
  1613. X    case 'V':    return ("f_relativize"); /* IDA sendmail */
  1614. X    default:
  1615. X    warn:
  1616. X        fprintf (stderr,
  1617. X            "warning: non standard mailer flag '%c' on line %d\n",
  1618. X                c, line);
  1619. X        buf[0] = c;
  1620. X        return buf;
  1621. X    }
  1622. X}
  1623. X
  1624. X#define doOundoc(val)    if (undoc) \
  1625. Xfprintf (stderr, "warning: undocumented option '%c' used on line %d\n", c, line);\
  1626. Xreturn (val)
  1627. X
  1628. X/* optionname --- convert sendmail options to ease names */
  1629. X
  1630. Xchar *optionname (c)
  1631. Xchar c;
  1632. X{
  1633. X    static char buf[2] = { '\0', '\0' };
  1634. X
  1635. X    switch (c) {
  1636. X    case 'A':    return ("o_alias");
  1637. X    case 'a':    return ("o_ewait");
  1638. X    case 'B':    return ("o_bsub");
  1639. X    case 'b':    return ("o_maxempty"); /* SunOS 4.0 */
  1640. X    case 'C':    doOundoc ("o_checkpoint");
  1641. X    case 'c':    return ("o_qwait");
  1642. X    case 'd':    return ("o_delivery");
  1643. X    case 'D':    return ("o_rebuild");
  1644. X    case 'e':    return ("o_handling");
  1645. X    case 'F':    return ("o_tmode");
  1646. X    case 'f':    return ("o_usave");
  1647. X    case 'g':    return ("o_gid");
  1648. X    case 'H':    return ("o_fsmtp");
  1649. X    case 'h':    return ("o_maxhops");    /* SunOS 4.0 */
  1650. X    case 'i':    return ("o_skipd");
  1651. X    case 'I':    return ("o_nameserver");    /* HP/UX */
  1652. X/*    case 'K':        Keyed Database (IDA) */
  1653. X    case 'L':    return ("o_slog");
  1654. X    case 'm':    return ("o_rsend");
  1655. X    case 'N':    return ("o_dnet");
  1656. X    case 'n':    doOundoc ("o_validate");
  1657. X    case 'o':    return ("o_hformat");
  1658. X    case 'P':       doOundoc ("o_pmaster");
  1659. X    case 'Q':    return ("o_qdir");
  1660. X    case 'q':    docompat ("o_qfactor");
  1661. X    case 'r':    return ("o_tread");
  1662. X    case 'R':    return ("o_nfs");    /* SunOS 4.0 */
  1663. X    case 'S':    return ("o_flog");
  1664. X    case 's':    return ("o_safe");
  1665. X    case 'T':    return ("o_qtimeout");
  1666. X    case 't':    return ("o_timezone");
  1667. X    case 'u':    return ("o_dmuid");
  1668. X    case 'v':    return ("o_verbose");
  1669. X    case 'W':    return ("o_wizpass");
  1670. X    case 'x':    return ("o_loadq");
  1671. X    case 'X':    return ("o_loadnc");
  1672. X    case 'Y':    if (sunos ) return ("o_aliasfile"); else docompat ("o_newproc");
  1673. X    case 'y':    docompat ("o_recipfactor");
  1674. X    case 'z':    docompat ("o_prifactor");
  1675. X    case 'Z':    docompat ("o_waitfactor");
  1676. X    case '/':    return ("o_envelope");    /* IDA */
  1677. X    default:
  1678. X    warn:
  1679. X        fprintf (stderr,
  1680. X            "warning: non standard option '%c' on line %d\n",
  1681. X                c, line);
  1682. X        buf[0] = c;
  1683. X        return buf;
  1684. X    }
  1685. X}
  1686. X
  1687. X/* delivoption --- convert sendmail delivery option value to ease name */
  1688. X
  1689. Xchar *delivoption (c)
  1690. Xchar c;
  1691. X{
  1692. X    static char buf[2] = { '\0', '\0' };
  1693. X
  1694. X    switch (c) {
  1695. X    case 'i':    return ("d_interactive");
  1696. X    case 'b':    return ("d_background");
  1697. X    case 'q':    return ("d_queue");
  1698. X    default:
  1699. X        fprintf (stderr,
  1700. X    "warning: non standard delivery option '%c' on line %d\n", c, line);
  1701. X        buf[0] = c;
  1702. X        return buf;
  1703. X    }
  1704. X}
  1705. X
  1706. X/* handle_option --- convert sendmail handling option value to ease name */
  1707. X
  1708. Xchar *handle_option (c)
  1709. Xchar c;
  1710. X{
  1711. X    static char buf[2] = { '\0', '\0' };
  1712. X
  1713. X    switch (c) {
  1714. X    case 'p':    return ("h_print");
  1715. X    case 'q':    return ("h_exit");
  1716. X    case 'm':    return ("h_mail");
  1717. X    case 'w':    return ("h_write");
  1718. X    case 'e':    return ("h_mailz");
  1719. X    default:
  1720. X        fprintf (stderr,
  1721. X    "warning: non standard handling option '%c' on line %d\n", c, line);
  1722. X        buf[0] = c;
  1723. X        return buf;
  1724. X    }
  1725. X}
  1726. X
  1727. X/*
  1728. X * "buffered" i/o routines. These are necessary since
  1729. X * mail headers may have continuation lines, and we can't see if
  1730. X * a continuation line is there without getting it. If it isn't,
  1731. X * just put it back.
  1732. X */
  1733. X
  1734. Xint saved = 0;
  1735. Xchar *saveb = NULL;
  1736. X
  1737. X/* ngets --- get a line of input from either saved buffer or stdin */
  1738. X
  1739. Xchar *ngets (bp)
  1740. Xchar *bp;
  1741. X{
  1742. X    if (! saved)
  1743. X        return (gets (bp));
  1744. X
  1745. X    saved = 0;
  1746. X    bp = saveb;
  1747. X    saveb = NULL;
  1748. X    return (bp);
  1749. X}
  1750. X
  1751. X/* ungets --- put a buffer back on the input, so to speak */
  1752. X
  1753. Xvoid ungets (bp)
  1754. Xchar *bp;
  1755. X{
  1756. X    saved = 1;
  1757. X    saveb = bp;
  1758. X    line--;
  1759. X}
  1760. END_OF_cfc/cfc.c
  1761. if test 39729 -ne `wc -c <cfc/cfc.c`; then
  1762.     echo shar: \"cfc/cfc.c\" unpacked with wrong size!
  1763. fi
  1764. chmod +x cfc/cfc.c
  1765. # end of overwriting check
  1766. fi
  1767. echo shar: End of archive 6 \(of 6\).
  1768. cp /dev/null ark6isdone
  1769. MISSING=""
  1770. for I in 1 2 3 4 5 6 ; do
  1771.     if test ! -f ark${I}isdone ; then
  1772.     MISSING="${MISSING} ${I}"
  1773.     fi
  1774. done
  1775. if test "${MISSING}" = "" ; then
  1776.     echo You have unpacked all 6 archives.
  1777.     rm -f ark[1-9]isdone
  1778. else
  1779.     echo You still need to unpack the following archives:
  1780.     echo "        " ${MISSING}
  1781. fi
  1782. ##  End of shell archive.
  1783. exit 0
  1784. --
  1785. Bruce G. Barnett    barnett@crd.ge.com    uunet!crdgw1!barnett
  1786.