summaryrefslogtreecommitdiff
path: root/src/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common.c')
-rw-r--r--src/common.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/src/common.c b/src/common.c
new file mode 100644
index 000000000..f21b49759
--- /dev/null
+++ b/src/common.c
@@ -0,0 +1,171 @@
+/* common.c --- Common routines, constants, etc. Used by all the wrappers.
+ *
+ * Copyright (C) 1998 by the Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "common.h"
+
+/* passed in by configure */
+#define SCRIPTDIR PREFIX ## "/scripts/" /* trailing slash */
+#define MODULEDIR PREFIX ## "/Mailman" /* no trailing slash */
+
+const char* prefixdir = PREFIX;
+const char* scriptdir = SCRIPTDIR;
+const char* moduledir = MODULEDIR;
+char* python = PYTHON;
+
+
+
+/* Report on errors and exit
+ */
+void
+fatal(const char* ident, const char* format, ...)
+{
+ char log_entry[1024];
+
+ va_list arg_ptr;
+ va_start(arg_ptr, format);
+ vsprintf(log_entry, format, arg_ptr);
+ va_end(arg_ptr);
+
+ /* Write to the console, maillog is often mostly ignored, and root
+ * should definitely know about any problems.
+ */
+ openlog(ident, LOG_CONS, LOG_MAIL);
+ syslog(LOG_ERR, "%s", log_entry);
+ closelog();
+ exit(1);
+}
+
+
+
+/* Is the parent process allowed to call us?
+ */
+void
+check_caller(const char* ident, uid_t parentuid, gid_t parentgid)
+{
+ /* compare to our parent's uid */
+ if (parentuid != getuid()) {
+ fatal(ident,
+ "Attempt to exec script with invalid uid %d, expected %d",
+ getuid(), parentuid);
+ }
+ if (parentgid != getgid()) {
+ fatal(ident,
+ "Attempt to exec script with invalid gid %d, expected %d",
+ getgid(), parentgid);
+ }
+}
+
+
+
+/* Run a Python script out of the script directory
+ *
+ * args[0] should be the abs path to the Python script to execute
+ * argv[1:] are other args for the script
+ * env may or may not contain PYTHONPATH, we'll substitute our own
+ */
+int
+run_script(const char* script, int argc, char** argv, char** env)
+{
+ const char envstr[] = "PYTHONPATH=";
+ const int envlen = strlen(envstr);
+
+ int envcnt = 0;
+ int i, j, status;
+ char** newenv;
+ char** newargv;
+
+ /* We want to tightly control how the CGI scripts get executed.
+ * For portability and security, the path to the Python executable
+ * is hard-coded into this C wrapper, rather than encoded in the #!
+ * line of the script that gets executed. So we invoke those
+ * scripts by passing the script name on the command line to the
+ * Python executable.
+ *
+ * We also need to hack on the PYTHONPATH environment variable so
+ * that the path to the installed Mailman modules will show up
+ * first on sys.path.
+ *
+ */
+ for (envcnt = 0; env[envcnt]; envcnt++)
+ ;
+
+ /* okay to be a little too big */
+ newenv = (char**)malloc(sizeof(char*) * (envcnt + 2));
+
+ /* filter out any existing PYTHONPATH in the environment */
+ for (i = 0, j = 0; i < envcnt; i++)
+ if (strncmp(envstr, env[i], envlen)) {
+ newenv[i] = env[j];
+ j++;
+ }
+
+ /* Tack on our own version of PYTHONPATH, which should contain only
+ * the path to the Mailman package modules.
+ *
+ * $(PREFIX)/modules
+ */
+ newenv[j] = (char*)malloc(sizeof(char) * (
+ strlen(envstr) +
+ strlen(moduledir) +
+ 1));
+ strcpy(newenv[j], envstr);
+ strcat(newenv[j], moduledir);
+ j++;
+
+ newenv[j] = NULL;
+
+ /* Now put together argv. This will contain first the absolute path
+ * to the python executable, then the absolute path to the script,
+ * then any additional args passed in argv above.
+ */
+ newargv = (char**)malloc(sizeof(char*) * (argc + 2));
+ newargv[0] = python;
+ newargv[1] = (char*)malloc(sizeof(char) * (
+ strlen(scriptdir) +
+ strlen(script) +
+ 1));
+ strcpy(newargv[1], scriptdir);
+ strcat(newargv[1], script);
+
+ /* now tack on all the rest of the arguments. we can skip argv's
+ * first two arguments because, for cgi-wrapper there is only argv[0].
+ * For mail-wrapper, argv[1] is the mail command (e.g. post,
+ * mailowner, or mailcmd) and argv[2] is the listname. The mail
+ * command to execute gets passed in as this function's `script'
+ * parameter and becomes the argument to the python interpreter. The
+ * list name therefore should become argv[2] to this process.
+ *
+ * TBD: have to make sure this works with alias-wrapper.
+ */
+ for (i = 2; i < argc; i++)
+ newargv[i] = argv[i];
+
+ newargv[i] = NULL;
+
+ status = execve(python, &newargv[0], &newenv[0]);
+ return status;
+}
+
+
+
+/*
+ * Local Variables:
+ * c-file-style: "python"
+ * End:
+ */