home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / ease3.5 / part06 < prev    next >
Encoding:
Internet Message Format  |  1991-12-09  |  46.8 KB

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