+\f/*
+** SETUSERENV -- set an environment in the propogated environment
+**
+** Parameters:
+** envar -- the name of the environment variable.
+** value -- the value to which it should be set. If
+** null, this is extracted from the incoming
+** environment. If that is not set, the call
+** to setuserenv is ignored.
+**
+** Returns:
+** none.
+*/
+
+void
+setuserenv(envar, value)
+ const char *envar;
+ const char *value;
+{
+ int i;
+ char **evp = UserEnviron;
+ char *p;
+
+ if (value == NULL)
+ {
+ value = getenv(envar);
+ if (value == NULL)
+ return;
+ }
+
+ i = strlen(envar);
+ p = (char *) xalloc(strlen(value) + i + 2);
+ strcpy(p, envar);
+ p[i++] = '=';
+ strcpy(&p[i], value);
+
+ while (*evp != NULL && strncmp(*evp, p, i) != 0)
+ evp++;
+ if (*evp != NULL)
+ {
+ *evp++ = p;
+ }
+ else if (evp < &UserEnviron[MAXUSERENVIRON])
+ {
+ *evp++ = p;
+ *evp = NULL;
+ }
+
+ /* make sure it is in our environment as well */
+ if (putenv(p) < 0)
+ syserr("setuserenv: putenv(%s) failed", p);
+}
+\f/*
+** DUMPSTATE -- dump state
+**
+** For debugging.
+*/
+
+void
+dumpstate(when)
+ char *when;
+{
+#ifdef LOG
+ register char *j = macvalue('j', CurEnv);
+
+ syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---",
+ when,
+ j == NULL ? "<NULL>" : j);
+ if (j != NULL)
+ {
+ if (!wordinclass(j, 'w'))
+ syslog(LOG_DEBUG, "*** $j not in $=w ***");
+ }
+ syslog(LOG_DEBUG, "--- open file descriptors: ---");
+ printopenfds(TRUE);
+ syslog(LOG_DEBUG, "--- connection cache: ---");
+ mci_dump_all(TRUE);
+ if (RewriteRules[89] != NULL)
+ {
+ int stat;
+ register char **pvp;
+ char *pv[MAXATOM + 1];
+
+ pv[0] = NULL;
+ stat = rewrite(pv, 89, 0, CurEnv);
+ syslog(LOG_DEBUG, "--- ruleset 89 returns stat %d, pv: ---",
+ stat);
+ for (pvp = pv; *pvp != NULL; pvp++)
+ syslog(LOG_DEBUG, "%s", *pvp);
+ }
+ syslog(LOG_DEBUG, "--- end of state dump ---");
+#endif
+}
+
+
+void
+sigusr1()
+{
+ dumpstate("user signal");
+}
+
+
+void
+sighup()
+{
+#ifdef LOG
+ if (LogLevel > 3)
+ syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]);
+#endif
+ execv(SaveArgv[0], (ARGV_T) SaveArgv);
+#ifdef LOG
+ if (LogLevel > 0)
+ syslog(LOG_ALERT, "could not exec %s: %m", SaveArgv[0]);
+#endif
+ exit(EX_OSFILE);
+}
+\f/*
+** TESTMODELINE -- process a test mode input line
+**
+** Parameters:
+** line -- the input line.
+** e -- the current environment.
+*/
+
+void
+testmodeline(line, e)
+ char *line;
+ ENVELOPE *e;
+{
+ register char *p;
+ char *q;
+ auto char *delimptr;
+ int mid;
+ ADDRESS a;
+ extern bool invalidaddr();
+ extern char *crackaddr();
+
+ switch (line[0])
+ {
+ case '#':
+ return;
+
+ case '.': /* config-style settings */
+ switch (line[1])
+ {
+ case 'D':
+ mid = macid(&line[2], &delimptr);
+ if (mid != '\0')
+ define(mid, newstr(delimptr), e);
+ break;
+
+ case 'C':
+ setclass(line[2], &line[3]);
+ break;
+
+ case 'S': /* dump rule set */
+ {
+ int rs;
+ struct rewrite *rw;
+ STAB *s;
+
+ if (line[2] == '\0')
+ return;
+ s = stab(&line[2], ST_RULESET, ST_FIND);
+ if (s == NULL)
+ {
+ if (!isdigit(line[2]))
+ return;
+ rs = atoi(line+2);
+ }
+ else
+ rs = s->s_ruleset;
+ if (rs < 0 || rs > MAXRWSETS)
+ return;
+ if ((rw = RewriteRules[rs]) == NULL)
+ return;
+ do
+ {
+ char **s;
+ putchar('R');
+ s = rw->r_lhs;
+ while (*s != NULL)
+ {
+ xputs(*s++);
+ putchar(' ');
+ }
+ putchar('\t');
+ putchar('\t');
+ s = rw->r_rhs;
+ while (*s != NULL)
+ {
+ xputs(*s++);
+ putchar(' ');
+ }
+ putchar('\n');
+ } while (rw = rw->r_next);
+ }
+ break;
+
+ default:
+ printf("Unknown config command %s", line);
+ break;
+ }
+ return;
+
+ case '-': /* set command-line-like opts */
+ switch (line[1])
+ {
+ case 'd':
+ tTflag(&line[2]);
+ break;
+
+ default:
+ printf("Unknown \"-\" command %s", line);
+ break;
+ }
+ return;
+
+ case '$':
+ mid = macid(&line[1], NULL);
+ if (mid == '\0')
+ return;
+ p = macvalue(mid, e);
+ if (p == NULL)
+ printf("Undefined\n");
+ else
+ {
+ xputs(p);
+ printf("\n");
+ }
+ return;
+
+ case '/': /* miscellaneous commands */
+ p = &line[strlen(line)];
+ while (--p >= line && isascii(*p) && isspace(*p))
+ *p = '\0';
+ p = strpbrk(line, " \t");
+ if (p != NULL)
+ {
+ while (isascii(*p) && isspace(*p))
+ *p++ = '\0';
+ }
+ else
+ p = "";
+ if (strcasecmp(&line[1], "mx") == 0)
+ {
+#if NAMED_BIND
+ /* look up MX records */
+ int nmx;
+ int i;
+ auto int rcode;
+ char *mxhosts[MAXMXHOSTS + 1];
+
+ nmx = getmxrr(p, mxhosts, FALSE, &rcode);
+ printf("getmxrr(%s) returns %d value(s):\n", p, nmx);
+ for (i = 0; i < nmx; i++)
+ printf("\t%s\n", mxhosts[i]);
+#else
+ printf("No MX code compiled in\n");
+#endif
+ }
+ else if (strcasecmp(&line[1], "try") == 0)
+ {
+ q = crackaddr(p);
+ printf("Cracked address = ");
+ xputs(q);
+ printf("\n");
+ if (parseaddr(p, &a, RF_COPYNONE, '\0', NULL, e) == NULL)
+ printf("Cannot parse\n");
+ else if (a.q_host != NULL && a.q_host[0] != '\0')
+ printf("mailer %s, host %s, user %s\n",
+ a.q_mailer->m_name, a.q_host, a.q_user);
+ else
+ printf("mailer %s, user %s\n",
+ a.q_mailer->m_name, a.q_user);
+ }
+ else
+ {
+ printf("Unknown test command %s\n", line);
+ }
+ return;
+ }
+
+ for (p = line; isascii(*p) && isspace(*p); p++)
+ continue;
+ q = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ if (*p == '\0')
+ {
+ printf("No address!\n");
+ return;
+ }
+ *p = '\0';
+ if (invalidaddr(p + 1, NULL))
+ return;
+ do
+ {
+ register char **pvp;
+ char pvpbuf[PSBUFSIZE];
+
+ pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf,
+ &delimptr, NULL);
+ if (pvp == NULL)
+ continue;
+ p = q;
+ while (*p != '\0')
+ {
+ int stat;
+
+ stat = rewrite(pvp, atoi(p), 0, e);
+ if (stat != EX_OK)
+ printf("== Ruleset %s status %d\n",
+ p, stat);
+ while (*p != '\0' && *p++ != ',')
+ continue;
+ }
+ } while (*(p = delimptr) != '\0');
+}