args->v[args->n++]= a;
}
-static void add_userv_var(const char *en, const char *ev,
- struct buildargs *args) {
+static void add_userv_var(const char *fulln,
+ const char *en, const char *ev, void *p) {
+ struct buildargs *args= p;
size_t l;
char *a;
int main(int argc, const char **argv) {
char *username;
- const char *slash2, *pathi, *ev, *en, *av;
- const char *const *ep;
+ const char *slash2, *pathi, *av;
size_t usernamelen, l;
struct buildargs args;
pid_t child, rchild;
if (!isalpha(username[0])) error("username 1st character is not alphabetic");
xsetenv("PATH_INFO",slash2,1);
- args.n= 0; args.max= argc + nenvok + 10;
+ args.n= 0; args.max= argc + MAX_ENVVARS + 10;
args.v= xmalloc(args.max * sizeof(*args.v));
addarg(&args, "userv");
if (debugmode) addarg(&args, "-DDEBUG=1");
- for (ep= envok; (en= *ep); ep++) {
- ev= getenv(en); if (!ev) continue;
- add_userv_var(en, ev, &args);
- }
+ filter_environment(FILTF_WILDCARD, "", envok, add_userv_var, &args);
addarg(&args, username);
addarg(&args, "www-cgi");
#define MAX_ARGS 1024
#define MAX_USERNAME_LEN 1024
#define MAX_SCRIPTPATH_LEN 1024
+#define MAX_ENVVAR_NAME 128
#define MAX_ENVVAR_VALUE (1024*1024)
+#define MAX_ENVVARS 256
void syserror(const char *m);
void error(const char *m);
void xsetenv(const char *en, const char *ev, int overwrite);
void *xrealloc(void *ptr, size_t sz);
+void filter_environment(unsigned flags, const char *prefix_in,
+ const char *const *patv,
+ void (*foundone)(const char *fulln, const char *en,
+ const char *ev, void *p),
+ void *p);
+#define FILTF_WILDCARD 1u
+
extern const char *const envok[];
extern const int nenvok;
extern int debugmode;
#include <string.h>
#include <errno.h>
+#include <unistd.h>
+
#include "ucgi.h"
const char *const envok[]= {
void xsetenv(const char *en, const char *ev, int overwrite) {
if (setenv(en,ev,overwrite)) syserror("setenv");
}
+
+void filter_environment(unsigned flags, const char *prefix_in,
+ const char *const *patv,
+ void (*foundone)(const char *fulln,
+ const char *en, const char *ev,
+ void *p),
+ void *p)
+{
+ char *const *ep;
+ const char *const *patp;
+ const char *en, *ev, *pat, *q;
+ char enbuf[MAX_ENVVAR_NAME];
+ size_t n, pn = strlen(prefix_in);
+ int acceptp;
+
+ D( if (debugmode) printf(";; filter_environment...\n"); )
+ for (ep= environ; (en= *ep); ep++) {
+ D( if (debugmode) printf(";; consider env-var `%s'\n", en); )
+ if (strncmp(en, prefix_in, pn) != 0 || !en[pn]) {
+ D( if (debugmode) printf(";; doesn't match prefix\n"); )
+ goto next_ev;
+ }
+ for (patp= patv; (pat= *patp); patp++) {
+ q= en + pn;
+ acceptp= 1;
+ if (*pat == '!' && (flags & FILTF_WILDCARD)) {
+ acceptp= 0; pat++;
+ }
+ for (;;) {
+ if (!*pat) {
+ if (*q != '=') {
+ D( if (debugmode)
+ printf(";; mismatch `%s' (prefix)\n", *patp); )
+ goto next_pat;
+ }
+ D( if (debugmode) printf(";; matched `%s'\n", *patp); )
+ ev = q + 1;
+ break;
+ } else if (*pat == '*' && (flags & FILTF_WILDCARD)) {
+ q = strchr(q, '=');
+ if (!q) {
+ D( if (debugmode)
+ printf(";; mismatch `%s' (discard: no `=')\n", *patp); )
+ goto next_ev;
+ }
+ D( if (debugmode)
+ printf(";; wildcard match for `%s'\n", *patp); )
+ ev = q + 1;
+ break;
+ } else
+ if (*pat++ != *q++) {
+ D( if (debugmode) printf(";; mismatch `%s'\n", *patp); )
+ goto next_pat;
+ }
+ }
+ if (acceptp) {
+ n= q - en;
+ if (n >= sizeof(enbuf))
+ error("environment variable name too long");
+ memcpy(enbuf, en, n);
+ enbuf[n]= 0;
+ D( if (debugmode)
+ printf(";; full = `%s'; tail = `%s'; value = `%s'\n",
+ enbuf, enbuf + pn, ev); )
+ foundone(enbuf, enbuf + pn, ev, p);
+ } D( else if (debugmode)
+ printf(";; matched negated pattern\n"); )
+ goto next_ev;
+ next_pat:;
+ }
+ next_ev:;
+ }
+}
#include "ucgi.h"
+static void setenvar(const char *fulln,
+ const char *en, const char *ep, void *p) {
+ xsetenv(en, ep, 1);
+ unsetenv(fulln);
+}
+
int main(int argc, const char **argv) {
- char *uservarn, *scriptpath, *newvar;
- const char *nextslash, *lastslash, *pathi, *ev, *ev2, *en, *scriptdir, *av;
- const char *const *ep;
+ char *scriptpath, *newvar;
+ const char *nextslash, *lastslash, *pathi, *ev, *ev2, *scriptdir, *av;
const char **arguments;
- size_t scriptdirlen, scriptpathlen, l, uservarnl;
+ size_t scriptdirlen, scriptpathlen, l;
struct stat stab;
int r, nargs;
scriptdir= newvar;
scriptdirlen= strlen(scriptdir);
- uservarn= 0;
- uservarnl= 0;
- for (ep= envok; (en= *ep); ep++) {
- l= strlen(en)+11;
- if (uservarnl<l) { uservarn= xrealloc(uservarn,l); uservarnl= l; }
- sprintf(uservarn,"USERV_U_E_%s",en);
- ev= getenv(uservarn); if (!ev) continue;
- if (strlen(ev) > MAX_ENVVAR_VALUE) error("environment variable too long");
- if (setenv(en,ev,1)) syserror("setenv");
- unsetenv(uservarn);
- }
+ filter_environment(0, "USERV_U_E_", envok, setenvar, 0);
scriptpath= 0;
pathi= getenv("PATH_INFO");