chiark / gitweb /
debugging for thing that crashed
[innduct.git] / innd / tcl.c
1 /*  $Id: tcl.c 6124 2003-01-14 06:03:29Z rra $
2 **
3 **  Support for TCL things
4 **
5 **  By Bob Heiney, Network Systems Laboratory, Digital Equipment Corporation
6 */
7
8 #include "config.h"
9 #include "clibrary.h"
10
11 #include "inn/innconf.h"
12 #include "innd.h"
13
14 #if     defined(DO_TCL)
15
16 Tcl_Interp       *TCLInterpreter;
17 bool             TCLFilterActive;
18 struct buffer    *TCLCurrArticle;
19 ARTDATA          *TCLCurrData;
20
21 static char      *TCLSTARTUP = NULL;
22 static char      *TCLFILTER = NULL;
23
24
25 void
26 TCLfilter(value)
27     bool value;
28 {
29     TCLFilterActive=value;
30
31     syslog(L_NOTICE, "%s tcl filtering %s", LogName,
32            TCLFilterActive ? "enabled" : "disabled");
33 }
34
35
36 void
37 TCLreadfilter(void)
38 {
39     int code;
40     
41     /* do before reload callback */
42     code = Tcl_Eval(TCLInterpreter, "filter_before_reload");
43     if (code != TCL_OK) {
44         if (strcmp(TCLInterpreter->result,
45                    "invalid command name: \"filter_before_reload\"")!=0)
46             syslog(L_ERROR, "%s Tcl filter_before_reload failed: %s",
47                    LogName, TCLInterpreter->result);
48     }
49
50     /* read the filter file */
51     if (TCLFILTER == NULL)
52         TCLFILTER = concatpath(innconf->pathfilter, _PATH_TCL_FILTER);
53     code = Tcl_EvalFile(TCLInterpreter, TCLFILTER);
54     if (code != TCL_OK) {
55         syslog(L_ERROR, "%s cant evaluate Tcl filter file: %s", LogName,
56                TCLInterpreter->result);
57         TCLfilter(false);
58     }
59
60     /* do the after callback, discarding any errors */
61     code = Tcl_Eval(TCLInterpreter, "filter_after_reload");
62     if (code != TCL_OK) {
63         if (strcmp(TCLInterpreter->result,
64                    "invalid command name: \"filter_after_reload\"")!=0)
65             syslog(L_ERROR, "%s Tcl filter_after_reload failed: %s",
66                    LogName, TCLInterpreter->result);
67     }
68 }
69
70
71 /* makeCheckSum
72  *
73  * Compute a checksum. This function does a one's-complement addition
74  * of a series of 32-bit words. "buflen" is in bytes, not words. This is 
75  * hard because the number of bits with which our machine can do arithmetic
76  * is the same as the size of the checksum being created, but our hardware
77  * is 2's-complement and C has no way to check for integer overflow.
78  *
79  * Note that the checksum is returned in network byte order and not host
80  * byte order; this makes it suitable for putting into packets and for
81  * comparing with what is found in packets.
82  */
83
84 static uint32_t
85 makechecksum(u_char *sumbuf, int buflen)
86 {
87     u_char *buf = (u_char *)sumbuf;
88     int32_t len = buflen;
89     int32_t sum;
90     uint32_t bwordl,bwordr,bword,suml,sumr;
91     int rmdr;
92     u_char tbuf[4];
93     u_char *ptbuf;
94
95     suml = 0; sumr = 0;
96
97     len = len/4;
98     rmdr = buflen - 4*len;
99
100     while (len-- > 0) {
101         bwordr = (buf[3] & 0xFF)
102             + ((buf[2] & 0xFF) << 8);
103         bwordl = (buf[1] & 0xFF)
104             + ((buf[0] & 0xFF) << 8);
105         bword = ( bwordl << 16) | bwordr;
106         bword = ntohl(bword);
107         bwordl = (bword >> 16) & 0xFFFF;
108         bwordr = bword & 0xFFFF;
109         sumr += bwordr;
110         if (sumr & ~0xFFFF) {
111             sumr &= 0xFFFF;
112             suml++;
113         }
114         suml += bwordl;
115         if (suml & ~0xFFFF) {
116             suml &= 0xFFFF;
117             sumr++;
118         }
119         buf += 4;
120     }
121     /* if buffer size was not an even multiple of 4 bytes,
122        we have work to do */
123     if (rmdr > 0) {
124         tbuf[3] = 0; tbuf[2] = 0; tbuf[1] = 0;
125         /* tbuf[0] will always be copied into, and tbuf[3] will
126          * always be zero (else this would not be a remainder)
127          */
128         ptbuf = tbuf;
129         while (rmdr--) *ptbuf++ = *buf++;
130         bwordr = (tbuf[3] & 0xFF)
131             + ((tbuf[2] & 0xFF) << 8);
132         bwordl = (tbuf[1] & 0xFF)
133             + ((tbuf[0] & 0xFF) << 8);
134         bword = ( bwordl << 16) | bwordr;
135         bword = ntohl(bword);
136         bwordl = (bword >> 16) & 0xFFFF;
137         bwordr = bword & 0xFFFF;
138         sumr += bwordr;
139         if (sumr & ~0xFFFF) {
140             sumr &= 0xFFFF;
141             suml++;
142         }
143         suml += bwordl;
144         if (suml & ~0xFFFF) {
145             suml &= 0xFFFF;
146             sumr++;
147         }
148     }
149     sum = htonl( (suml << 16) | sumr);
150     return (~sum);
151 }
152
153
154 int
155 TCLCksumArt(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
156 {
157     char buf[100];
158
159     snprintf(buf, sizeof(buf), "%08x",
160              makechecksum(TCLCurrArticle->data + TCLCurrData->Body,
161                           TCLCurrData->Body));
162     Tcl_SetResult(interp, buf, TCL_VOLATILE);
163     return TCL_OK;
164 }
165
166
167 void
168 TCLsetup(void)
169 {
170     int code;
171     
172     TCLInterpreter = Tcl_CreateInterp();
173     if (TCLSTARTUP == NULL)
174         TCLSTARTUP = concatpath(innconf->pathfilter, _PATH_TCL_STARTUP);
175     code = Tcl_EvalFile(TCLInterpreter, TCLSTARTUP);
176     if (code != TCL_OK) {
177         syslog(L_FATAL, "%s cant read Tcl startup file: %s", LogName,
178                TCLInterpreter->result);
179         exit(1);
180     }
181
182     Tcl_CreateCommand(TCLInterpreter, "checksum_article", TCLCksumArt,
183                       NULL, NULL);
184
185     TCLfilter(true);
186     TCLreadfilter();
187 }
188
189
190 void
191 TCLclose(void)
192 {
193 }
194
195
196 #endif /* defined(DO_TCL) */