home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / mail / delivery / deliver.tz / deliver / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-07  |  16.4 KB  |  811 lines

  1. /* $Header: main.c,v 2.12 90/03/07 11:00:58 chip Exp $
  2.  *
  3.  * A program to deliver local mail with some flexibility.
  4.  *
  5.  * $Log:    main.c,v $
  6.  * Revision 2.12  90/03/07  11:00:58  chip
  7.  * Debugging messages only when verbose.  (Sigh.)
  8.  * 
  9.  * Revision 2.11  90/03/06  13:11:53  chip
  10.  * Run error delivery file after normal delivery;
  11.  * then call delivery routines again afterward.
  12.  * 
  13.  * Revision 2.10  90/03/06  12:21:13  chip
  14.  * Move logging into log.c and address parsing into addr.c.
  15.  * New: error delivery file for messages that fail.
  16.  * Major rearrangement of delivery file code.
  17.  * 
  18.  * Revision 2.9  90/02/23  15:05:15  chip
  19.  * Clean up the setuid/setgid renunciation logic.
  20.  * 
  21.  * Revision 2.8  90/02/23  14:16:47  chip
  22.  * Support "#!" in delivery files.
  23.  * Support "user|program" and "user?error" from delivery files.
  24.  * Improve debugging and error message formatting.
  25.  * Rearrange code for clarity.
  26.  * 
  27.  * Revision 2.7  90/02/06  11:56:40  chip
  28.  * Enforce MBX_MODE regardless of UMASK.
  29.  * Enforce ordered logging with a log lockfile.
  30.  * Revise log format.
  31.  * 
  32.  * Revision 2.6  89/12/19  16:45:26  network
  33.  * Include <time.h> for the functions.
  34.  * 
  35.  * Revision 2.5  89/12/19  16:29:32  network
  36.  * Make timezone handling portable to System V.
  37.  * 
  38.  * Revision 2.4  89/11/10  12:23:55  network
  39.  * Handle recursion.  Enhance logging.
  40.  * 
  41.  * Revision 2.3  89/11/01  12:19:02  network
  42.  * Delintify.
  43.  * 
  44.  * Revision 2.2  89/11/01  11:51:47  network
  45.  * Add logging.
  46.  * 
  47.  * Revision 2.1  89/06/09  12:25:32  network
  48.  * Update RCS revisions.
  49.  * 
  50.  * Revision 1.13  89/06/09  12:23:53  network
  51.  * Baseline for 2.0 release.
  52.  * 
  53.  */
  54.  
  55. #include "deliver.h"
  56. #include "patchlevel.h"
  57. #include <signal.h>
  58.  
  59. /*
  60.  * External data.
  61.  */
  62.  
  63. /* Variables set by getopt() [blech] */
  64.  
  65. extern  int     optind, opterr;
  66. extern  char    *optarg;
  67.  
  68. /*
  69.  * Local data
  70.  */
  71.  
  72. static  char    dfl_sys[] = SYS_DELIVER;
  73. static  char    dfl_post[] = POST_DELIVER;
  74. static  char    dfl_err[] = ERR_DELIVER;
  75. static  char    dfl_user[] = USER_DELIVER;
  76.  
  77. /*
  78.  * Global data
  79.  */
  80.  
  81. int     verbose         = FALSE;
  82. int     dryrun          = FALSE;
  83. int     rundfiles       = TRUE;
  84. int     printaddrs      = FALSE;
  85. int     leavetemps      = FALSE;
  86. int     boxdelivery     = FALSE;
  87.  
  88. char    *progname       = "deliver";
  89. char    version[32]     = "2.0";
  90. char    *shell          = SHELL;
  91.  
  92. int     rec_level       = 0;
  93. int     rec_parent      = -1;
  94. char    *sys_deliver    = dfl_sys;
  95. char    *post_deliver   = dfl_post;
  96. char    *err_deliver    = dfl_err;
  97. char    *user_deliver   = dfl_user;
  98. char    *sender         = NULL;
  99. char    *hostname       = NULL;
  100.  
  101. int     eff_uid         = -1;
  102. int     eff_gid         = -1;
  103. int     real_uid        = -1;
  104. int     real_gid        = -1;
  105.  
  106. CONTEXT *eff_ct         = NULL;
  107. CONTEXT *real_ct        = NULL;
  108.  
  109. int     trust_user      = FALSE;
  110. int     trust_delfiles  = FALSE;
  111. FILE    *log            = NULL;
  112. char    *logfile        = NULL;
  113. FILE    *errlog         = NULL;
  114. char    *errlogfile     = NULL;
  115.  
  116. int     tty_input       = FALSE;
  117. SIGFLAG got_sig         = FALSE;
  118.  
  119. char    *ttype[T_MAX]   = { "header", "body", "header copy", "body copy" };
  120. char    *tfile[T_MAX]   = { NULL, NULL, NULL, NULL };
  121. char    *tenv[T_MAX]    = { NULL, NULL, ENV_HEADER, ENV_BODY };
  122. int     tfd[T_MAX]      = { -1, -1, -1, -1 };
  123.  
  124. /*
  125.  * Local functions.
  126.  */
  127.  
  128. static  SIGTYPE sighup(), sigint(), sigquit();
  129.  
  130. /*----------------------------------------------------------------------
  131.  * The Program.
  132.  */
  133.  
  134. main(argc, argv)
  135. int     argc;
  136. char    **argv;
  137. {
  138.     char    *p;
  139.     int     i, c, errcount, copy;
  140.  
  141.     /* Make sure that stdout and stderr are interleaved correctly */
  142.  
  143.     Linebuf(stdout);
  144.     Linebuf(stderr);
  145.  
  146.     /* Figure out the name used to invoke this program. */
  147.  
  148.     progname = basename(argv[0]);
  149.  
  150.     /* Special hack -- handle the recursion level and parent first. */
  151.  
  152.     if ((p = getenv(ENV_DLEVEL)) != NULL && (i = atoi(p)) > 0)
  153.         rec_level = i;
  154.  
  155.     if ((p = getenv(ENV_DPID)) != NULL && (i = atoi(p)) > 0)
  156.         rec_parent = i;
  157.  
  158.     /* If recursion level is non-zero, append it to the program name. */
  159.  
  160.     if (rec_level > 0)
  161.     {
  162.         char    *np;
  163.  
  164.         np = zalloc((unsigned) strlen(progname) + 16);
  165.         (void) sprintf(np, "%s[%d]", progname, rec_level);
  166.         progname = np;
  167.     }
  168.  
  169.     /* What version of the program is this? */
  170.  
  171.     (void) sprintf(version + strlen(version), ".%02d", PATCHLEVEL);
  172.  
  173.     /* Let's be sane about the file creation mask. */
  174.  
  175.     (void) umask(UMASK);
  176.  
  177.     /* Find effective and real uids and gids. */
  178.  
  179.     eff_uid = geteuid();
  180.     eff_gid = getegid();
  181.     real_uid = getuid();
  182.     real_gid = getgid();
  183.  
  184.     /* Make sure that setuidness is reasonable. */
  185.  
  186.     if (eff_uid != real_uid && eff_uid != 0)
  187.     {
  188.         error("if setuid, must be setuid root\n");
  189.         leave(1);
  190.     }
  191.  
  192.     /* Process environment: handle recursive invocation. */
  193.  
  194.     if ((p = getenv(ENV_DFLAGS)) != NULL)
  195.     {
  196.         while (*p)
  197.         {
  198.             switch (*p++)
  199.             {
  200.             case 'v':
  201.                 verbose = TRUE;
  202.                 break;
  203.             case 'd':
  204.                 verbose = TRUE;
  205.                 dryrun = TRUE;
  206.                 break;
  207.             case 'A':
  208.                 printaddrs = TRUE;
  209.                 dryrun = TRUE;
  210.                 break;
  211.             case 'n':
  212.                 rundfiles = FALSE;
  213.                 break;
  214.             case 't':
  215.                 leavetemps = TRUE;
  216.                 break;
  217.             }
  218.         }
  219.     }
  220.  
  221.     if ((p = getenv(ENV_SYSDEL)) != NULL && *p)
  222.         sys_deliver = p;
  223.     if ((p = getenv(ENV_POSTDEL)) != NULL && *p)
  224.         post_deliver = p;
  225.     if ((p = getenv(ENV_ERRDEL)) != NULL && *p)
  226.         err_deliver = p;
  227.     if ((p = getenv(ENV_USERDEL)) != NULL && *p)
  228.         user_deliver = p;
  229.  
  230.     if ((p = getenv(ENV_SENDER)) != NULL && *p)
  231.         sender = p;
  232.     if ((p = getenv(ENV_HOSTNAME)) != NULL && *p)
  233.         hostname = p;
  234.  
  235.     /* Parse command line arguments */
  236.  
  237.     while ((c = getopt(argc, argv, "vdAntbs:p:e:u:r:h:")) != EOF)
  238.     {
  239.         switch (c)
  240.         {
  241.         case 'v':
  242.             verbose = TRUE;
  243.             break;
  244.         case 'd':
  245.             verbose = TRUE;
  246.             dryrun = TRUE;
  247.             break;
  248.         case 'A':
  249.             printaddrs = TRUE;
  250.             dryrun = TRUE;
  251.             break;
  252.         case 'n':
  253.             rundfiles = FALSE;
  254.             break;
  255.         case 't':
  256.             leavetemps = TRUE;
  257.             break;
  258.         case 'b':
  259.             boxdelivery = TRUE;
  260.             break;
  261.         case 's':
  262.             if (*optarg)
  263.                 sys_deliver = optarg;
  264.             break;
  265.         case 'p':
  266.             if (*optarg)
  267.                 post_deliver = optarg;
  268.             break;
  269.         case 'e':
  270.             if (*optarg)
  271.                 err_deliver = optarg;
  272.             break;
  273.         case 'u':
  274.             if (*optarg)
  275.                 user_deliver = optarg;
  276.             break;
  277.         case 'r':
  278.             if (*optarg)
  279.                 sender = optarg;
  280.             break;
  281.         case 'h':
  282.             if (*optarg)
  283.                 hostname = optarg;
  284.             break;
  285.         case '?':
  286.             usage();
  287.         }
  288.     }
  289.  
  290.     /* Open temporary log files. */
  291.  
  292.     openlogs();
  293.  
  294.     /* Figure out the name of this host, unless we've been told. */
  295.  
  296.     if (!hostname && (hostname = gethost()) == NULL)
  297.     {
  298.         hostname = "unknown";
  299.         error("unable to determine host name; using \"%s\"\n",
  300.               hostname);
  301.     }
  302.  
  303.     /* If no destinations were given, forget it. */
  304.  
  305.     if (optind >= argc)
  306.     {
  307.         error("no recipients specified\n");
  308.         usage();
  309.     }
  310.  
  311.     /* If debugging, print a nice banner. */
  312.  
  313.     if (verbose)
  314.     {
  315.         message("%s %s running on host %s\n",
  316.             progname, version, hostname);
  317.     }
  318.  
  319.     /*
  320.      * Renounce setuid privileges if:
  321.      *   1.  We don't trust the real user id, OR
  322.      *   2.  The caller is using non-default delivery file names.
  323.      */
  324.  
  325.     if (trusted_uid(real_uid))
  326.         trust_user = TRUE;
  327.  
  328.     if (strcmp(dfl_sys, sys_deliver) == 0
  329.      && strcmp(dfl_post, post_deliver) == 0
  330.      && strcmp(dfl_err, err_deliver) == 0
  331.      && strcmp(dfl_user, user_deliver) == 0)
  332.         trust_delfiles = TRUE;
  333.  
  334.     if ((!trust_user && !trust_delfiles)
  335.      && (eff_uid != real_uid || eff_gid != real_gid))
  336.     {
  337.         if (setuid(real_uid) == -1)
  338.         {
  339.             syserr("can't renounce setuid privileges");
  340.             leave(1);
  341.         }
  342.         if (setgid(real_gid) == -1)
  343.         {
  344.             syserr("can't renounce setgid privileges");
  345.             leave(1);
  346.         }
  347.  
  348.         if ((eff_uid = geteuid()) != real_uid
  349.          || (eff_gid = getegid()) != real_gid)
  350.         {
  351.             error("kernel bug: can't renounce setuid/setgid");
  352.             leave(1);
  353.         }
  354.  
  355.         if (verbose)
  356.             message("renounced setuid privileges\n");
  357.     }
  358.  
  359.     /* Get the contexts of our effective and real uids. */
  360.  
  361.     if ((eff_ct = uid_context(eff_uid)) == NULL)
  362.         error("invalid effective uid %d!?\n", eff_uid);
  363.  
  364.     if ((real_ct = uid_context(real_uid)) == NULL)
  365.         error("invalid real uid %d!?\n", real_uid);
  366.  
  367.     if (!eff_ct || !real_ct)
  368.         leave(1);
  369.  
  370.     if (verbose)
  371.     {
  372.         message("effective uid = %s (%d/%d); real uid = %s (%d/%d)\n",
  373.             eff_ct->ct_name, eff_ct->ct_uid, eff_ct->ct_gid,
  374.             real_ct->ct_name, real_ct->ct_uid, real_ct->ct_gid);
  375.     }
  376.  
  377.     /*
  378.      * Where is the message coming from?
  379.      */
  380.  
  381.     if (isatty(0))
  382.         tty_input = TRUE;
  383.  
  384.     /*
  385.      * If we are not going to deliver, or if we are receiving the
  386.      * message from a tty, catch signals so we can remove temp files.
  387.      * Otherwise, ignore signals.
  388.      */
  389.  
  390.     if (dryrun || tty_input)
  391.         catch_sigs();
  392.     else
  393.         ignore_sigs();
  394.  
  395.     /*
  396.      * Create the temporary files and write the message to them.
  397.      */
  398.  
  399.     copy = copy_message();
  400.  
  401.     /*
  402.      * No more signals...
  403.      */
  404.  
  405.     ignore_sigs();
  406.  
  407.     /*
  408.      * ... but if we had already caught a signal,
  409.      *     or if copy_msg() had a problem, leave.
  410.      */
  411.  
  412.     if ((copy < 0) || got_sig)
  413.     {
  414.         if (got_sig)
  415.             error("caught signal - exiting\n");
  416.         leave(1);
  417.     }
  418.  
  419.     /*
  420.      * Set up useful environment variables.
  421.      * Note that this must be done _after_ copy_message(),
  422.      * since that's where the temp files are created.
  423.      */
  424.  
  425.     setup_environ();
  426.  
  427.     /*
  428.      * If recursion is too deep, consider mail undeliverable.
  429.      */
  430.  
  431.     if (rec_level > REC_LIMIT)
  432.         main_toodeep();
  433.  
  434.     /*
  435.      * Else if the "-b" flag was specified, arguments are mailboxes.
  436.      */
  437.  
  438.     else if (boxdelivery)
  439.         main_boxes(argc - optind, argv + optind);
  440.  
  441.     /*
  442.      * Otherwise, arguments are addresses.
  443.      */
  444.  
  445.     else
  446.         main_addrs(argc - optind, argv + optind);
  447.  
  448.     /*
  449.      * Do all delivery.
  450.      * If anything happens, print a debugging message.
  451.      */
  452.  
  453.     i = 0;
  454.     i += (mbox_deliver() > 0);
  455.     i += (prog_deliver() > 0);
  456.     i += (uucp_deliver() > 0);
  457.     if (i > 0 && verbose)
  458.         dumpdests("after delivery");
  459.  
  460.     /*
  461.      * If we're not in mailbox mode, and if the error delivery file
  462.      * executes, deliver to any destination(s) that it generated.
  463.      */
  464.  
  465.     if (!boxdelivery
  466.      && (i = err_dfile()) > 0)
  467.     {
  468.         if (verbose)
  469.             dumpdests("after running error delivery file");
  470.  
  471.         i = 0;
  472.         i += (mbox_deliver() > 0);
  473.         i += (prog_deliver() > 0);
  474.         i += (uucp_deliver() > 0);
  475.         if (i > 0 && verbose)
  476.             dumpdests("after delivery to error destinations");
  477.     }
  478.  
  479.     /*
  480.      * Report all results in log file.
  481.      */
  482.  
  483.     logreport(argc - optind, argv + optind);
  484.  
  485.     /*
  486.      * Report any errors.
  487.      */
  488.  
  489.     errcount = report_errors(argc - optind, argv + optind);
  490.  
  491.     /*
  492.      * All done.
  493.      */
  494.  
  495.     leave(errcount ? 1 : 0);
  496.     /* NOTREACHED */
  497. }
  498.  
  499. /*----------------------------------------------------------------------
  500.  * Normal address handling.
  501.  * Call system delivery file, user delivery files,
  502.  * post-user delivery file, error delivery file.
  503.  */
  504.  
  505. main_addrs(ac, av)
  506. int    ac;
  507. char    **av;
  508. {
  509.     int    n;
  510.  
  511.     /* Run all destinations though the system delivery file. */
  512.  
  513.     if (sys_dfile(ac, av) >= 0)
  514.     {
  515.         if (verbose)
  516.             dumpdests("after running system delivery file");
  517.     }
  518.     else
  519.     {
  520.         int     a;
  521.  
  522.         /*
  523.          * System delivery file is missing or ignored.
  524.          * Use the argument list verbatim.
  525.          */
  526.  
  527.         for (a = 0; a < ac; ++a)
  528.             (void) addr_dest(av[a], (CONTEXT *)NULL);
  529.  
  530.         if (verbose)
  531.             dumpdests("as taken from argument list");
  532.     }
  533.  
  534.     /*
  535.      * Run each user destination through his delivery file.
  536.      */
  537.  
  538.     n = user_dfiles();
  539.     if (n > 0 && verbose)
  540.         dumpdests("after running user delivery files");
  541.  
  542.     /*
  543.      * Run each remaining destination though the post-user
  544.      * delivery file.
  545.      */
  546.  
  547.     n = post_dfile();
  548.     if (n > 0 && verbose)
  549.         dumpdests("after running post-user delivery file");
  550. }
  551.  
  552. /*----------------------------------------------------------------------
  553.  * Consider all arguments as mailbox filenames.
  554.  */
  555.  
  556. main_boxes(ac, av)
  557. int    ac;
  558. char    **av;
  559. {
  560.     int     a;
  561.  
  562.     if (verbose)
  563.         message("mailbox delivery as %s\n", real_ct->ct_name);
  564.  
  565.     for (a = 0; a < ac; ++a)
  566.         (void) dest(real_ct->ct_name, CL_MBOX, av[a]);
  567.  
  568.     if (verbose)
  569.         dumpdests("(should all be mailboxes)");
  570. }
  571.  
  572. /*----------------------------------------------------------------------
  573.  * Recursion too deep.  Bail out.
  574.  */
  575.  
  576. main_toodeep()
  577. {
  578.     error("recursion limit (%d) exceeded; writing to %s:%s",
  579.           REC_LIMIT, eff_ct->ct_name, MBX_UNDEL);
  580.  
  581.     dest_undel(eff_ct->ct_name);
  582. }
  583.  
  584. /*----------------------------------------------------------------------
  585.  * Print a usage message and exit.
  586.  */
  587.  
  588. usage()
  589. {
  590.     message("Usage: %s [-b][-A][-d][-v][-n][-t][-r from][-h host] args\n", progname);
  591.     message("-b       All arguments are mailbox filenames.\n");
  592.     message("         (Default: arguments are user names.)\n");
  593.     message("-A       Resolve addresses but do not deliver.\n");
  594.     message("-d       Be verbose but do not deliver.\n");
  595.     message("-v       Be verbose and deliver.\n");
  596.     message("-n       Do not run any delivery files.\n");
  597.     message("-t       Do not remote temp files before exiting.\n");
  598.     message("-s file  Specify the system delivery filename.\n");
  599.     message("-p file  Specify the post-user delivery filename.\n");
  600.     message("-e file  Specify the error delivery filename.\n");
  601.     message("-u file  Specify the user delivery filename.\n");
  602.     message("-r from  Specify the address to appear in the \"From \" line.\n");
  603.     message("-h host  Specify the host name.\n");
  604.     message("args     Either user addresses or mailboxes (-b).\n");
  605.     leave(1);
  606. }
  607.  
  608. /*----------------------------------------------------------------------
  609.  * Clean up and exit.
  610.  */
  611.  
  612. leave(code)
  613. int     code;
  614. {
  615.     /* Report vital statistics if something went wrong. */
  616.  
  617.     errinfo();
  618.  
  619.     /* Discard temporary files. */
  620.  
  621.     if (! leavetemps)
  622.     {
  623.         int     t;
  624.  
  625.         for (t = 0; t < T_MAX; ++t)
  626.         {
  627.             if (tfd[t] != -1)
  628.                 (void) close(tfd[t]);
  629.             if (tfile[t] && unlink(tfile[t]) == -1)
  630.                 syserr("can't unlink %s", tfile[t]);
  631.         }
  632.     }
  633.  
  634.     /* Save temporary logs by appending to real logfiles. */
  635.  
  636.     savelogs();
  637.  
  638.     /* Discard temporary logs unless user requested otherwise. */
  639.  
  640.     if (!leavetemps)
  641.         tosslogs();
  642.  
  643.     /* "I am outa here." */
  644.  
  645.     exit(code);
  646. }
  647.  
  648. /*----------------------------------------------------------------------
  649.  * Catch signals.
  650.  */
  651.  
  652. catch_sigs()
  653. {
  654.     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  655.         (void) signal(SIGHUP, sighup);
  656.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  657.         (void) signal(SIGINT, sigint);
  658.     if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  659.         (void) signal(SIGQUIT, sigquit);
  660. }
  661.  
  662. /*----------------------------------------------------------------------
  663.  * Ignore signals.
  664.  */
  665.  
  666. ignore_sigs()
  667. {
  668.     (void) signal(SIGHUP, SIG_IGN);
  669.     (void) signal(SIGINT, SIG_IGN);
  670.     (void) signal(SIGQUIT, SIG_IGN);
  671. }
  672.  
  673. static SIGTYPE
  674. sighup()
  675. {
  676.     (void) signal(SIGHUP, sighup);
  677.     got_sig = TRUE;
  678. }
  679.  
  680. static SIGTYPE
  681. sigint()
  682. {
  683.     (void) signal(SIGINT, sigint);
  684.     got_sig = TRUE;
  685. }
  686.  
  687. static SIGTYPE
  688. sigquit()
  689. {
  690.     (void) signal(SIGQUIT, sigquit);
  691.     got_sig = TRUE;
  692. }
  693.  
  694. /*----------------------------------------------------------------------
  695.  * Report any errors to stderr.
  696.  * Return an error count.
  697.  */
  698.  
  699. int
  700. report_errors(ac, av)
  701. int    ac;
  702. char    **av;
  703. {
  704.     DEST    **dv;
  705.     int    i, count, errcount;
  706.  
  707.     if ((dv = dest_array(&count)) == NULL)
  708.         return 0;
  709.  
  710.     errcount = 0;
  711.     for (i = 0; i < count; ++i)
  712.     {
  713.         DEST    *d;
  714.         char    *e;
  715.         int    len;
  716.  
  717.         d = dv[i];
  718.  
  719.         if (d->d_state != ST_ERROR)
  720.             continue;
  721.  
  722.         if (++errcount == 1)
  723.         {
  724.             int    a;
  725.  
  726.             error("delivery error on host %s.\n", hostname);
  727.             message("Delivery to %s address%s failed:\n",
  728.                 ac ? "these" : "this",
  729.                 ac ? "es" : "");
  730.             for (a = 0; a < ac; ++a)
  731.                 message("\t%s\n", av[a]);
  732.             message("Reason(s) for failure:\n");
  733.         }
  734.  
  735.         message("\t\"%s\"", d->d_name);
  736.         if (d->d_class == CL_MBOX)
  737.             message(", mailbox \"%s\"", d->d_param);
  738.         else if (d->d_class == CL_PROG)
  739.             message(", program \"%s\"", d->d_param);
  740.  
  741.         e = derrmsg(d);
  742.         len = strlen(d->d_name) + strlen(e);
  743.         if (d->d_param)
  744.             len += strlen(d->d_param);
  745.         message(":%s%s\n", (len > 60) ? "\n\t\t" : " ", derrmsg(d));
  746.     }
  747.  
  748.     free((char *) dv);
  749.  
  750.     return errcount;
  751. }
  752.  
  753. /*----------------------------------------------------------------------
  754.  * Is the given uid trusted?
  755.  */
  756.  
  757. int
  758. trusted_uid(uid)
  759. int     uid;
  760. {
  761.     CONTEXT *ct;
  762.     char    **n;
  763.     static char *t[] = { TRUSTED_USERS, 0 };
  764.  
  765.     for (n = t; *n; ++n)
  766.     {
  767.         if ((ct = name_context(*n)) != NULL && uid == ct->ct_uid)
  768.             return TRUE;
  769.     }
  770.  
  771.     return FALSE;
  772. }
  773.  
  774. /*----------------------------------------------------------------------
  775.  * Set up useful environment variables.
  776.  */
  777.  
  778. setup_environ()
  779. {
  780.     char    s[8];
  781.     int     f = 0;
  782.  
  783.     (void) sprintf(s, "%d", getpid());
  784.     alloc_env(ENV_DPID, s);
  785.  
  786.     (void) sprintf(s, "%d", rec_level + 1);
  787.     alloc_env(ENV_DLEVEL, s);
  788.  
  789.     s[f++] = '-';
  790.     if (verbose)
  791.         s[f++] = (dryrun ? 'd' : 'v');
  792.     if (printaddrs)
  793.         s[f++] = 'A';
  794.     if (leavetemps)
  795.         s[f++] = 't';
  796.     s[f] = 0;
  797.     alloc_env(ENV_DFLAGS, (f > 1) ? s : "");
  798.  
  799.     if (sys_deliver && *sys_deliver)
  800.         alloc_env(ENV_SYSDEL, sys_deliver);
  801.     if (user_deliver && *user_deliver)
  802.         alloc_env(ENV_USERDEL, user_deliver);
  803.     if (hostname && *hostname)
  804.         alloc_env(ENV_HOSTNAME, hostname);
  805.     if (sender && *sender)
  806.         alloc_env(ENV_SENDER, sender);
  807.  
  808.     alloc_env("IFS", " \t\n");
  809.     del_env("ENV");         /* in case SHELL is ksh */
  810. }
  811.