There are no available options for this view.

Parent Directory Parent Directory | Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a> Revision <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Log">Log</a>

Revision 1.15 - (show annotations) (download) (as text)
Tue Oct 11 08:03:27 2011 UTC (6 years, 2 months ago) by dvrsn
Branch: MAIN
CVS Tags: aolserver_v45_r2_rc0, HEAD
Branch point for: aolserver_v45_r2
Changes since 1.14: +40 -8 lines
File MIME type: text/x-chdr
add various functions, mostly from SF RFEs -
pre-write filter, response content modification,
insert/append filter, priority filters, ns_conn gzip flag,
re-run filters on redirect with new config option "filterredirect",
add new constants, fix STREQ macro
1 /*
2 * The contents of this file are subject to the AOLserver Public License
3 * Version 1.1 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://aolserver.com/.
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 * the License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Original Code is AOLserver Code and related documentation
13 * distributed by AOL.
14 *
15 * The Initial Developer of the Original Code is America Online,
16 * Inc. Portions created by AOL are Copyright (C) 1999 America Online,
17 * Inc. All Rights Reserved.
18 *
19 * Alternatively, the contents of this file may be used under the terms
20 * of the GNU General Public License (the "GPL"), in which case the
21 * provisions of GPL are applicable instead of those above. If you wish
22 * to allow use of your version of this file only under the terms of the
23 * GPL and not to allow others to use your version of this file under the
24 * License, indicate your decision by deleting the provisions above and
25 * replace them with the notice and other provisions required by the GPL.
26 * If you do not delete the provisions above, a recipient may use your
27 * version of this file under either the License or the GPL.
28 */
29
30 /*
31 * tclrequest.c --
32 *
33 * Routines for Tcl proc and ADP registered requests.
34 */
35
36 static const char *RCSID = "@(#) $Header: /cvsroot-fuse/aolserver/aolserver/nsd/tclrequest.c,v 1.15 2011/10/11 08:03:27 dvrsn Exp $, compiled: " __DATE__ " " __TIME__;
37
38 #include "nsd.h"
39
40 #define ARGS_UNKNOWN (-1)
41 #define ARGS_FAILED (-2)
42
43 /*
44 * The following structure defines the proc callback context.
45 */
46
47 typedef struct {
48 char *name;
49 char *args;
50 int nargs;
51 } Proc;
52
53 /*
54 * Local functions defined in this file
55 */
56
57 static Ns_OpProc <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_ProcRequest">ProcRequest</a>;
58 static Ns_OpProc <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AdpRequest">AdpRequest</a>;
59 static Ns_FilterProc <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_ProcFilter">ProcFilter</a>;
60 static Proc *<a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NewProc">NewProc</a>(char *name, char *args);
61 static Ns_Callback <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_FreeProc">FreeProc</a>;
62 static void <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AppendConnId">AppendConnId</a>(Tcl_DString *dsPtr, Ns_Conn *conn);
63 static int <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_RegisterFilterObj">RegisterFilterObj</a>(NsInterp *itPtr, int when, int objc,
64 Tcl_Obj *CONST objv[]);
65 static int <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_GetNumArgs">GetNumArgs</a>(Tcl_Interp *interp, Proc *procPtr);
66
67
68 /*
69 *----------------------------------------------------------------------
70 *
71 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_Ns_TclRequest">Ns_TclRequest</a> --
72 *
73 * Dummy up a direct call to TclProcRequest for a connection.
74 *
75 * Results:
76 * See TclDoOp.
77 *
78 * Side effects:
79 * None.
80 *
81 *----------------------------------------------------------------------
82 */
83
84 int
85 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_Ns_TclRequest">Ns_TclRequest</a>(Ns_Conn *conn, char *name)
86 {
87 Proc proc;
88
89 proc.name = name;
90 proc.args = NULL;
91 proc.nargs = 0;
92 return <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_ProcRequest">ProcRequest</a>(&proc, conn);
93 }
94
95
96 /*
97 *----------------------------------------------------------------------
98 *
99 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterProcObjCmd">NsTclRegisterProcObjCmd</a> --
100 *
101 * Implements ns_register_proc as obj command.
102 *
103 * Results:
104 * Tcl result.
105 *
106 * Side effects:
107 * See docs.
108 *
109 *----------------------------------------------------------------------
110 */
111
112 int
113 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterProcObjCmd">NsTclRegisterProcObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc,
114 Tcl_Obj *CONST objv[], int adp)
115 {
116 int flags, idx;
117 Proc *procPtr;
118 NsInterp *itPtr = arg;
119 char *server, *method, *url, *name, *args;
120
121 if (objc < 4 || objc > 7) {
122 badargs:
123 Tcl_WrongNumArgs(interp, 1, objv, "?-noinherit? method url proc ?args?");
124 return TCL_ERROR;
125 }
126 if (STREQ(Tcl_GetString(objv[1]), "-noinherit")) {
127 if (objc < 5) {
128 goto badargs;
129 }
130 flags = NS_OP_NOINHERIT;
131 idx = 2;
132 } else {
133 if (objc == 7) {
134 goto badargs;
135 }
136 flags = 0;
137 idx = 1;
138 }
139 if (<a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_NsTclGetServer">NsTclGetServer</a>(itPtr, &server) != TCL_OK) {
140 return TCL_ERROR;
141 }
142 method = Tcl_GetString(objv[idx++]);
143 url = Tcl_GetString(objv[idx++]);
144 name = Tcl_GetString(objv[idx++]);
145 args = (idx < objc ? Tcl_GetString(objv[idx]) : NULL);
146 procPtr = <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NewProc">NewProc</a>(name, args);
147 <a href="/cvs/aolserver/aolserver/nsd/op.c#A_Ns_RegisterRequest">Ns_RegisterRequest</a>(server, method, url, <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_ProcRequest">ProcRequest</a>, <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_FreeProc">FreeProc</a>,
148 procPtr, flags);
149 return TCL_OK;
150 }
151
152
153 /*
154 *----------------------------------------------------------------------
155 *
156 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterAdpObjCmd">NsTclRegisterAdpObjCmd</a> --
157 *
158 * Implements ns_register_adp as obj command.
159 *
160 * Results:
161 * Tcl result.
162 *
163 * Side effects:
164 * See docs.
165 *
166 *----------------------------------------------------------------------
167 */
168
169 int
170 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterAdpObjCmd">NsTclRegisterAdpObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
171 {
172 NsInterp *itPtr = arg;
173 char *server, *method, *url, *file;
174
175 if (objc != 4 && objc != 5) {
176 badargs:
177 Tcl_WrongNumArgs(interp, 1, objv, "?-noinherit? method url file");
178 return TCL_ERROR;
179 }
180 if (objc == 5 && !STREQ(Tcl_GetString(objv[1]), "-noinherit")) {
181 goto badargs;
182 }
183 if (<a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_NsTclGetServer">NsTclGetServer</a>(itPtr, &server) != TCL_OK) {
184 return TCL_ERROR;
185 }
186 method = Tcl_GetString(objv[objc-3]);
187 url = Tcl_GetString(objv[objc-2]);
188 file = ns_strdup(Tcl_GetString(objv[objc-1]));
189 <a href="/cvs/aolserver/aolserver/nsd/op.c#A_Ns_RegisterRequest">Ns_RegisterRequest</a>(server, method, url, <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AdpRequest">AdpRequest</a>, ns_free,
190 file, objc == 5 ? NS_OP_NOINHERIT : 0);
191 return TCL_OK;
192 }
193
194
195 /*
196 *----------------------------------------------------------------------
197 *
198 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclUnRegisterObjCmd">NsTclUnRegisterObjCmd</a> --
199 *
200 * Implements ns_unregister_proc and ns_unregister_adp commands.
201 *
202 * Results:
203 * Tcl result.
204 *
205 * Side effects:
206 * See docs.
207 *
208 *----------------------------------------------------------------------
209 */
210
211 int
212 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclUnRegisterObjCmd">NsTclUnRegisterObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
213 {
214 NsInterp *itPtr = arg;
215 char *server;
216
217 if (objc != 3 && objc != 4) {
218 Tcl_WrongNumArgs(interp, 1, objv, "?-noinherit? method url");
219 return TCL_ERROR;
220 }
221 if (objc == 4 && !STREQ(Tcl_GetString(objv[1]), "-noinherit")) {
222 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "unknown flag \"",
223 Tcl_GetString(objv[1]),
224 "\": should be -noinherit", NULL);
225 return TCL_ERROR;
226 }
227 if (<a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_NsTclGetServer">NsTclGetServer</a>(itPtr, &server) != TCL_OK) {
228 return TCL_ERROR;
229 }
230 <a href="/cvs/aolserver/aolserver/nsd/op.c#A_Ns_UnRegisterRequest">Ns_UnRegisterRequest</a>(server, Tcl_GetString(objv[objc-2]), Tcl_GetString(objv[objc-1]),
231 objc == 3 ? 1 : 0);
232 return TCL_OK;
233 }
234
235
236 /*
237 *----------------------------------------------------------------------
238 *
239 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterFilterObjCmd">NsTclRegisterFilterObjCmd</a> --
240 *
241 * Implements ns_register_filter.
242 *
243 * Results:
244 * Tcl result.
245 *
246 * Side effects:
247 * See docs.
248 *
249 *----------------------------------------------------------------------
250 */
251
252 int
253 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterFilterObjCmd">NsTclRegisterFilterObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
254 {
255 NsInterp *itPtr = arg;
256 int lobjc;
257 Tcl_Obj **lobjv;
258 int when, i;
259 static CONST char *wopt[] = {
260 "read", "prewrite", "write", "prequeue", "preauth", "postauth", "trace", NULL
261 };
262 enum {
263 ReadIdx, PreWriteIdx, WriteIdx, PreQueueIdx, PreAuthIdx, PostAuthIdx, TraceIdx,
264 } widx;
265
266 if (objc < 2) {
267 error:
268 Tcl_SetResult(interp, "wrong arguments: should be ns_register_filter "
269 "?-insert? ?-priority num? when method url script ?arg?",
270 TCL_STATIC);
271 return TCL_ERROR;
272 }
273 when = 0;
274 for (i = 1; i < objc; i++) {
275 char *arg = Tcl_GetString(objv[i]);
276 if (*arg != '-') break;
277 if (STRIEQ(arg, "-insert")) {
278 when |= NS_FILTER_INSERT;
279 } else if (STRIEQ(arg, "-priority")) {
280 if (++i >= objc) goto error;
281 int prio;
282 if (Tcl_GetIntFromObj(interp,objv[i],&prio) != TCL_OK) {
283 return TCL_ERROR;
284 }
285 if (prio < -128 || prio > 127) {
286 Tcl_SetResult(interp, "priority must be in range -128 .. 127",
287 TCL_STATIC);
288 return TCL_ERROR;
289 }
290 when |= NS_FILTER_PRIORITY(prio);
291 } else {
292 goto error;
293 }
294 }
295 objc-=(i-1);
296 objv+=(i-1);
297
298 if (objc < 5 || objc > 6) {
299 goto error;
300 }
301 if (Tcl_ListObjGetElements(interp, objv[1], &lobjc, &lobjv) != TCL_OK) {
302 return TCL_ERROR;
303 }
304 for (i = 0; i < lobjc; ++i) {
305 if (Tcl_GetIndexFromObj(interp, lobjv[i], wopt, "when", 0,
306 (int *) &widx) != TCL_OK) {
307 return TCL_ERROR;
308 }
309 switch (widx) {
310 case ReadIdx:
311 when |= NS_FILTER_READ;
312 break;
313 case PreWriteIdx:
314 when |= NS_FILTER_PRE_WRITE;
315 break;
316 case WriteIdx:
317 when |= NS_FILTER_WRITE;
318 break;
319 case PreQueueIdx:
320 when |= NS_FILTER_PRE_QUEUE;
321 break;
322 case PreAuthIdx:
323 when |= NS_FILTER_PRE_AUTH;
324 break;
325 case PostAuthIdx:
326 when |= NS_FILTER_POST_AUTH;
327 break;
328 case TraceIdx:
329 when |= NS_FILTER_TRACE;
330 break;
331 }
332 }
333 if (when == 0) {
334 Tcl_SetResult(interp, "blank filter when specification", TCL_STATIC);
335 return TCL_ERROR;
336 }
337 return <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_RegisterFilterObj">RegisterFilterObj</a>(itPtr, when, objc - 2, objv + 2);
338 }
339
340
341 /*
342 *----------------------------------------------------------------------
343 *
344 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterTraceObjCmd">NsTclRegisterTraceObjCmd</a> --
345 *
346 * Implements ns_register_trace as obj command.
347 *
348 * Results:
349 * Tcl result.
350 *
351 * Side effects:
352 * See docs.
353 *
354 *----------------------------------------------------------------------
355 */
356
357 int
358 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterTraceObjCmd">NsTclRegisterTraceObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
359 {
360 NsInterp *itPtr = arg;
361
362 if (objc != 4 && objc != 5) {
363 Tcl_WrongNumArgs(interp, 1, objv, "method urlPattern script ?arg?");
364 return TCL_ERROR;
365 }
366 return <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_RegisterFilterObj">RegisterFilterObj</a>(itPtr, NS_FILTER_VOID_TRACE, objc - 1, objv + 1);
367 }
368
369
370 /*
371 *----------------------------------------------------------------------
372 *
373 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterFastPathObjCmd">NsTclRegisterFastPathObjCmd</a> --
374 *
375 * Implements ns_register_fastpath as obj command.
376 *
377 * Results:
378 * Tcl result.
379 *
380 * Side effects:
381 * See docs.
382 *
383 *----------------------------------------------------------------------
384 */
385
386 int
387 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NsTclRegisterFastPathObjCmd">NsTclRegisterFastPathObjCmd</a>(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
388 {
389 NsInterp *itPtr = arg;
390 NsServer *servPtr = itPtr->servPtr;
391 char *server, *method, *url;
392 int flags, idx;
393
394 if (objc < 3 || objc > 4) {
395 badargs:
396 Tcl_WrongNumArgs(interp, 1, objv, "?-noinherit? method url");
397 return TCL_ERROR;
398 }
399 flags = 0;
400 idx = 1;
401 if (objc == 4) {
402 if (!STREQ(Tcl_GetString(objv[1]), "-noinherit")) {
403 goto badargs;
404 }
405 flags = NS_OP_NOINHERIT;
406 idx++;
407 }
408 server = servPtr->server;
409 method = Tcl_GetString(objv[idx++]);
410 url = Tcl_GetString(objv[idx++]);
411 <a href="/cvs/aolserver/aolserver/nsd/op.c#A_Ns_RegisterRequest">Ns_RegisterRequest</a>(server, method, url, <a href="/cvs/aolserver/aolserver/nsd/fastpath.c#A_Ns_FastPathOp">Ns_FastPathOp</a>, NULL, servPtr, flags);
412 return TCL_OK;
413 }
414
415
416 /*
417 *----------------------------------------------------------------------
418 *
419 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AdpRequest">AdpRequest</a> --
420 *
421 * Ns_OpProc for registered ADP's.
422 *
423 * Results:
424 * See <a href="/cvs/aolserver/aolserver/nsd/adprequest.c#A_Ns_AdpRequest">Ns_AdpRequest</a>.
425 *
426 * Side effects:
427 * None.
428 *
429 *----------------------------------------------------------------------
430 */
431
432 static int
433 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AdpRequest">AdpRequest</a>(void *arg, Ns_Conn *conn)
434 {
435 return <a href="/cvs/aolserver/aolserver/nsd/adprequest.c#A_Ns_AdpRequest">Ns_AdpRequest</a>(conn, (char *) arg);
436 }
437
438
439 /*
440 *----------------------------------------------------------------------
441 *
442 * RequstProc --
443 *
444 * Ns_OpProc for ns_register_proc callbacks. Constructs and
445 * evaluates the given script.
446 *
447 * Results:
448 * Standard request result.
449 *
450 * Side effects:
451 * None.
452 *
453 *----------------------------------------------------------------------
454 */
455
456 static int
457 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_ProcRequest">ProcRequest</a>(void *arg, Ns_Conn *conn)
458 {
459 Proc *procPtr = arg;
460 Tcl_Interp *interp = <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_GetConnInterp">Ns_GetConnInterp</a>(conn);
461 int result, cnt;
462 Tcl_DString script;
463
464
465 /*
466 * Construct and evaluate the script. The legacy connId parameter is
467 * no longer required so the code below supports three cases:
468 *
469 * 1. No args: Append nothing.
470 * 2. One arg: Append the callback arg only.
471 * 3. Two or more args: Append the connId and callback arg.
472 */
473
474 Tcl_DStringInit(&script);
475 Tcl_DStringAppendElement(&script, procPtr->name);
476 cnt = <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_GetNumArgs">GetNumArgs</a>(interp, procPtr);
477 if (cnt != 0) {
478 if (cnt > 1) {
479 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AppendConnId">AppendConnId</a>(&script, conn);
480 }
481 Tcl_DStringAppendElement(&script, procPtr->args ? procPtr->args : "");
482 }
483 result = Tcl_EvalEx(interp, script.string, script.length, 0);
484 Tcl_DStringFree(&script);
485
486 /*
487 * On script error, generate an internal error response if
488 * no content has been sent on the connection.
489 */
490
491 if (result != TCL_OK) {
492 <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_TclLogError">Ns_TclLogError</a>(interp);
493 if (<a href="/cvs/aolserver/aolserver/nsd/return.c#A_Ns_ConnResetReturn">Ns_ConnResetReturn</a>(conn) == NS_OK) {
494 return <a href="/cvs/aolserver/aolserver/nsd/return.c#A_Ns_ConnReturnInternalError">Ns_ConnReturnInternalError</a>(conn);
495 }
496 }
497
498 return NS_OK;
499 }
500
501
502 /*
503 *----------------------------------------------------------------------
504 *
505 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_ProcFilter">ProcFilter</a> --
506 *
507 * Callback for Tcl-based connection filters.
508 *
509 * Results:
510 * Standard filter result.
511 *
512 * Side effects:
513 * None.
514 *
515 *----------------------------------------------------------------------
516 */
517
518 static int
519 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_ProcFilter">ProcFilter</a>(void *arg, Ns_Conn *conn, int why)
520 {
521 Proc *procPtr = arg;
522 Tcl_Interp *interp = <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_GetConnInterp">Ns_GetConnInterp</a>(conn);
523 Tcl_DString script;
524 int status, cnt;
525 CONST char *result;
526
527 /*
528 * Construct and evaluate the script. The filter arg and legacy connId
529 * args will be appended before the "why" argument if present.
530 */
531
532 Tcl_DStringInit(&script);
533 Tcl_DStringAppendElement(&script, procPtr->name);
534 cnt = <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_GetNumArgs">GetNumArgs</a>(interp, procPtr);
535 if (cnt > 1) {
536 if (cnt > 2) {
537 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AppendConnId">AppendConnId</a>(&script, conn);
538 }
539 Tcl_DStringAppendElement(&script, procPtr->args ? procPtr->args : "");
540 }
541 switch (why) {
542 case NS_FILTER_READ:
543 Tcl_DStringAppendElement(&script, "read");
544 break;
545 case NS_FILTER_PRE_WRITE:
546 Tcl_DStringAppendElement(&script, "prewrite");
547 break;
548 case NS_FILTER_WRITE:
549 Tcl_DStringAppendElement(&script, "write");
550 break;
551 case NS_FILTER_PRE_QUEUE:
552 Tcl_DStringAppendElement(&script, "prequeue");
553 break;
554 case NS_FILTER_PRE_AUTH:
555 Tcl_DStringAppendElement(&script, "preauth");
556 break;
557 case NS_FILTER_POST_AUTH:
558 Tcl_DStringAppendElement(&script, "postauth");
559 break;
560 case NS_FILTER_TRACE:
561 Tcl_DStringAppendElement(&script, "trace");
562 break;
563 default:
564 /* NB: Do not append a why argument. */
565 break;
566 }
567 Tcl_AllowExceptions(interp);
568 status = Tcl_EvalEx(interp, script.string, script.length, 0);
569 Tcl_DStringFree(&script);
570 if (status != TCL_OK) {
571 <a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_Ns_TclLogError">Ns_TclLogError</a>(interp);
572 }
573
574 /*
575 * Determine the filter return code from the Tcl result string.
576 */
577
578 if (why == NS_FILTER_VOID_TRACE) {
579 /* NB: <a href="/cvs/aolserver/aolserver/nsd/tclresp.c#A_Result">Result</a> string ignored for traces. */
580 status = NS_OK;
581 } else if (status != TCL_OK) {
582 /* NB: Filter error on script error. */
583 status = NS_ERROR;
584 } else {
585 result = Tcl_GetStringResult(interp);
586 if (STREQ(result, "filter_ok")) {
587 status = NS_OK;
588 } else if (STREQ(result, "filter_break")) {
589 status = NS_FILTER_BREAK;
590 } else if (STREQ(result, "filter_return")) {
591 status = NS_FILTER_RETURN;
592 } else {
593 <a href="/cvs/aolserver/aolserver/nsd/log.c#A_Ns_Log">Ns_Log</a>(Warning, "tclfilter: %s return invalid result: %s",
594 procPtr->name, result);
595 status = NS_ERROR;
596 }
597 }
598 return status;
599 }
600
601
602 /*
603 *----------------------------------------------------------------------
604 *
605 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_GetNumArgs">GetNumArgs</a> --
606 *
607 * Get the number of arguments for a given callback, invoked
608 * the first time the callback is used.
609 *
610 * Results:
611 * Number of args or -1 on error.
612 *
613 * Side effects:
614 * Will invoke script to determine arg count.
615 *
616 *----------------------------------------------------------------------
617 */
618
619 static int
620 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_GetNumArgs">GetNumArgs</a>(Tcl_Interp *interp, Proc *procPtr)
621 {
622 Tcl_Obj *objPtr;
623 Tcl_DString ds;
624
625 if (procPtr->nargs == ARGS_UNKNOWN) {
626 Tcl_DStringInit(&ds);
627 Tcl_DStringAppend(&ds, "llength [info args ", -1);
628 Tcl_DStringAppendElement(&ds, procPtr->name);
629 Tcl_DStringAppend(&ds, "]", 1);
630 if (Tcl_Eval(interp, ds.string) != TCL_OK) {
631 procPtr->nargs = ARGS_FAILED;
632 } else {
633 objPtr = Tcl_GetObjResult(interp);
634 if (Tcl_GetIntFromObj(interp, objPtr, &procPtr->nargs) != TCL_OK) {
635 procPtr->nargs = ARGS_FAILED;
636 }
637 }
638 Tcl_DStringFree(&ds);
639 }
640 return procPtr->nargs;
641 }
642
643
644 /*
645 *----------------------------------------------------------------------
646 *
647 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_RegisterFilterObj">RegisterFilterObj</a> --
648 *
649 * Register a Tcl filter.
650 *
651 * Results:
652 * TCL_ERROR if no server, TCL_OK otherwise.
653 *
654 * Side effects:
655 * Will register a filter to run later.
656 *
657 *----------------------------------------------------------------------
658 */
659
660 static int
661 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_RegisterFilterObj">RegisterFilterObj</a>(NsInterp *itPtr, int when, int objc, Tcl_Obj *CONST objv[])
662 {
663 Proc *procPtr;
664 char *server, *method, *url, *name, *args;
665
666 if (<a href="/cvs/aolserver/aolserver/nsd/tclinit.c#A_NsTclGetServer">NsTclGetServer</a>(itPtr, &server) != TCL_OK) {
667 return TCL_ERROR;
668 }
669 method = Tcl_GetString(objv[0]);
670 url = Tcl_GetString(objv[1]);
671 name = Tcl_GetString(objv[2]);
672 args = (objc > 3 ? Tcl_GetString(objv[3]) : NULL);
673 procPtr = <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NewProc">NewProc</a>(name, args);
674 <a href="/cvs/aolserver/aolserver/nsd/filter.c#A_Ns_RegisterFilter">Ns_RegisterFilter</a>(server, method, url, <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_ProcFilter">ProcFilter</a>, when, procPtr);
675 return TCL_OK;
676 }
677
678
679 /*
680 *----------------------------------------------------------------------
681 *
682 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AppendConnId">AppendConnId</a> --
683 *
684 * Append the Tcl conn handle to a dstring.
685 *
686 * Results:
687 * None.
688 *
689 * Side effects:
690 * Appends to the dstring.
691 *
692 *----------------------------------------------------------------------
693 */
694
695 static void
696 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_AppendConnId">AppendConnId</a>(Tcl_DString *dsPtr, Ns_Conn *conn)
697 {
698 Conn *connPtr = (Conn *) conn;
699
700 Tcl_DStringAppendElement(dsPtr, connPtr->idstr);
701 }
702
703
704 /*
705 *----------------------------------------------------------------------
706 *
707 * <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NewProc">NewProc</a>, <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_FreeProc">FreeProc</a> --
708 *
709 * Create or delete a Proc structure.
710 *
711 * Results:
712 * For <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NewProc">NewProc</a>, pointer to new Proc.
713 *
714 * Side effects:
715 * None.
716 *
717 *----------------------------------------------------------------------
718 */
719
720 static Proc *
721 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_NewProc">NewProc</a>(char *name, char *args)
722 {
723 Proc *procPtr;
724
725 procPtr = ns_malloc(sizeof(Proc));
726 procPtr->name = ns_strdup(name);
727 procPtr->args = ns_strcopy(args);
728 procPtr->nargs = ARGS_UNKNOWN;
729 return procPtr;
730 }
731
732 static void
733 <a href="/cvs/aolserver/aolserver/nsd/tclrequest.c#A_FreeProc">FreeProc</a>(void *arg)
734 {
735 Proc *procPtr = arg;
736
737 ns_free(procPtr->name);
738 if (procPtr->args != NULL) {
739 ns_free(procPtr->args);
740 }
741 ns_free(procPtr);
742 }