static int run_handler()

in tcl_core.c [550:746]


static int run_handler(request_rec *r, int hh)
{
	int xx = HTTP_NOT_FOUND, i;
	tcl_config_rec *tclr = (tcl_config_rec*) ap_get_module_config(r->per_dir_config, &tcl_module);
	size_t flen;
	file_cache *fptr = NULL, *fa = (file_cache*) fcache->elts;
	var_cache *vl = (var_cache*) tclr->var_list->elts;
	struct stat st;
	char *tmp_filename;
	
	if (!interp) {
		return DECLINED;
	}
	
	/* handler wasn't set so ignore it */
	if (!tclr->handlers[hh]) {
		return DECLINED;
	}
	
	if (hh != 8) {
		if (hh < 2) {
			tmp_filename = tclr->file_location[hh];
		}
		else {
			tmp_filename = r->filename;
		}
		
		/* this will be rewritten by some translation... */
		r->filename = tclr->file_location[hh];
	}
	else if (r->finfo.filetype != APR_REG) {
		ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "request URI does not match a file, a translation phase may have failed, r->filename = %s", r->filename);
		return DECLINED;
	}
	
	flen = strlen(r->filename);
	stat(r->filename, &st);
	
	for (i = 0; i < fcache->nelts; i++) {
		if (!strcmp(fa[i].file, r->filename)) {
			fptr = &(fa[i]);
			break;
		}
	}

	if (!fptr) {
		int fd;
		void *mptr;
		char *bptr;
		off_t pos = 0;
		Tcl_Obj *obj;
		
		if ((fd = open(r->filename, O_RDONLY, 0)) == -1) {
			ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "open(%s, ...): %s", r->filename, strerror(errno));
			
			return HTTP_NOT_FOUND;
		}

#ifdef HAVE_MMAP
		mptr = mmap((caddr_t) 0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
#else
		mptr = malloc(st.st_size);
		read(fd, mptr, st.st_size);
#endif /* HAVE_MMAP */

		bptr = (char*) malloc(st.st_size + flen + 21);
		
		memcpy(bptr, "namespace eval ", 15);		pos += 15;
		memcpy(bptr + pos, r->filename, flen);		pos += flen;
		memcpy(bptr + pos, " {\n", 3);				pos += 3;
		memcpy(bptr + pos, mptr, st.st_size);		pos += st.st_size;
		memcpy(bptr + pos, "\n}\0", 3);
		
#ifdef HAVE_MMAP
		munmap((char*) mptr, st.st_size);
#else
		free(mptr);
#endif /* HAVE_MMAP */

		close(fd);
		
		fptr = (file_cache*) apr_array_push(fcache);
		
		fptr->file = apr_pstrdup(fcache->pool, r->filename);
		memcpy(&(fptr->st), &st, sizeof(struct stat));
		
		obj = Tcl_NewStringObj(bptr, -1);
		
		free(bptr);
		
		if (Tcl_EvalObjEx(interp, obj, 0) == TCL_ERROR) {
			ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "Tcl_EvalObjEx(...): %s\n%s", Tcl_GetStringResult(interp), Tcl_GetVar(interp, "errorInfo", 0));
			return HTTP_INTERNAL_SERVER_ERROR;
		}
		
		for (i = 0; i < tclr->var_list->nelts; i++) {
			if (vl[i].fl == 1) {
				char *namespc = (char*) malloc(strlen(r->filename) + strlen(vl[i].var1) + 3);
				
				sprintf(namespc, "%s::%s", r->filename, vl[i].var1);
				set_var(interp, namespc, vl[i].var2, "%s", vl[i].var3);
				free(namespc);
			}
			else if (vl[i].fl == 2) {
				char *namespc = (char*) malloc(strlen(r->filename) + strlen(vl[i].var1) + 3);
				
				sprintf(namespc, "%s::%s", r->filename, vl[i].var1);
				run_script(interp, "lappend %s %s", namespc, vl[i].var2);
				free(namespc);
			}
		}
		
		if (raw_tcl) {
			run_script(interp, "namespace eval %s { %s }", r->filename, raw_tcl);
		}
	}
	else if (st.st_mtime > fptr->st.st_mtime) {
		int fd;
		void *mptr;
		char *bptr;
		off_t pos = 0;
		Tcl_Obj *obj;
		
		if ((fd = open(r->filename, O_RDONLY, 0)) == -1) {
			ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "open(%s, ...): %s", r->filename, strerror(errno));
			return HTTP_INTERNAL_SERVER_ERROR;
		}
		
#ifdef HAVE_MMAP
		mptr = mmap((caddr_t) 0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
#else
		mptr = malloc(st.st_size);
		read(fd, mptr, st.st_size);
#endif /* HAVE_MMAP */

		bptr = malloc(st.st_size + flen + 21);
		
		memcpy(bptr, "namespace eval ", 15);		pos += 15;
		memcpy(bptr + pos, r->filename, flen);		pos += flen;
		memcpy(bptr + pos, " {\n", 3);				pos += 3;
		memcpy(bptr + pos, mptr, st.st_size);	pos += st.st_size;
		memcpy(bptr + pos, "\n}\0", 3);
		
#ifdef HAVE_MMAP
		munmap((char*) mptr, st.st_size);
#else
		free(mptr);
#endif /* HAVE_MMAP */

		close(fd);
		
		fptr = (file_cache*) apr_array_push(fcache);
		
		fptr->file = apr_pstrdup(fcache->pool, r->filename);
		memcpy(&(fptr->st), &st, sizeof(struct stat));
		
		obj = Tcl_NewStringObj(bptr, -1);
		
		free(bptr);
		
		if (Tcl_EvalObjEx(interp, obj, 0) == TCL_ERROR) {
			ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "Tcl_EvalObjEx(...): %s\n%s", Tcl_GetStringResult(interp), Tcl_GetVar(interp, "errorInfo", 0));
			return HTTP_INTERNAL_SERVER_ERROR;
		}
	}
	
	_r = r;
	current_namespace = r->filename;
	read_post_ok = 1;
	
	{
		char *eptr = (char*) malloc(strlen(tclr->handlers[hh]) + flen + 3);
		Tcl_Obj *obj;
		
		sprintf(eptr, "%s::%s", fptr->file, tclr->handlers[hh]);
		
		obj = Tcl_NewStringObj(eptr, -1);
		
		free(eptr);
		
		if (Tcl_EvalObjEx(interp, obj, 0) == TCL_ERROR) {
			ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "Tcl_EvalObjEx(%s): %s", eptr, Tcl_GetStringResult(interp));
			
			r->content_type = "text/html";
			
			ap_rprintf(r, "<H3>TCL Error</H3><BR><PRE>%s</PRE>", Tcl_GetString(Tcl_GetVar2Ex(interp, "errorInfo", NULL, 0)));
			
			return OK;
		}
		
		Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &xx);
	}
	
	r->filename = tmp_filename;
	
	return xx;
}