Bug fix: Function ir_tcl_grs_del sometimes free'd bad memory.
[ir-tcl-moved-to-github.git] / grs.c
1 /*
2  * IR toolkit for tcl/tk
3  * (c) Index Data 1995
4  * See the file LICENSE for details.
5  * Sebastian Hammer, Adam Dickmeiss
6  *
7  * $Log: grs.c,v $
8  * Revision 1.5  1996-05-29 20:28:08  adam
9  * Bug fix: Function ir_tcl_grs_del sometimes free'd bad memory.
10  *
11  * Revision 1.4  1996/05/29  06:37:42  adam
12  * Function ir_tcl_get_grs_r enhanced so that specific elements can be
13  * extracted.
14  *
15  * Revision 1.3  1996/03/05 09:21:01  adam
16  * Bug fix: memory used by GRS records wasn't freed.
17  * Rewrote some of the error handling code - the connection is always
18  * closed before failback is called.
19  * If failback is defined the send APDU methods (init, search, ...) will
20  * return OK but invoke failback (as is the case if the write operation
21  * fails).
22  * Bug fix: ref_count in assoc object could grow if fraction of PDU was
23  * read.
24  *
25  * Revision 1.2  1995/09/20  11:37:01  adam
26  * Configure searches for tk4.1 and tk7.5.
27  * Work on GRS.
28  *
29  * Revision 1.1  1995/08/29  15:38:34  adam
30  * Added grs.c. new version.
31  *
32  */
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <assert.h>
38
39 #include "ir-tclp.h"
40
41 void ir_tcl_grs_del (IrTcl_GRS_Record **grs_record)
42 {
43     struct GRS_Record_entry *e;
44     int i;
45
46     while (!*grs_record)
47         return;
48     e = (*grs_record)->entries;
49     for (i = 0; i < (*grs_record)->noTags; i++, e++)
50     {
51         switch (e->tagWhich)
52         {
53         case Z_StringOrNumeric_numeric:
54             break;
55         default:
56             free (e->tagVal.str);
57         }
58         switch (e->dataWhich)
59         {
60         case Z_ElementData_octets:
61             free (e->tagData.octets.buf);
62             break;
63         case Z_ElementData_numeric:
64             break;
65         case Z_ElementData_date:
66             free (e->tagData.str);
67             break;            
68         case Z_ElementData_ext:
69             break;
70         case Z_ElementData_string:
71             free (e->tagData.str);
72             break;
73         case Z_ElementData_trueOrFalse:
74         case Z_ElementData_oid:
75         case Z_ElementData_intUnit:
76         case Z_ElementData_elementNotThere:
77         case Z_ElementData_elementEmpty:
78         case Z_ElementData_noDataRequested:
79         case Z_ElementData_diagnostic:
80             break;
81         case Z_ElementData_subtree:
82             ir_tcl_grs_del (&e->tagData.sub);
83             break;
84         }
85     }
86     free ((*grs_record)->entries);
87     free (*grs_record);
88     *grs_record = NULL;
89 }
90
91 void ir_tcl_grs_mk (Z_GenericRecord *r, IrTcl_GRS_Record **grs_record)
92 {
93     int i;
94     struct GRS_Record_entry *e;
95
96     *grs_record = NULL;
97     if (!r)
98         return;
99     *grs_record = ir_tcl_malloc (sizeof(**grs_record));
100     if (!((*grs_record)->noTags = r->num_elements))
101     {
102         (*grs_record)->entries = NULL;
103         return;
104     }
105     e = (*grs_record)->entries = ir_tcl_malloc (r->num_elements *
106                                                 sizeof(*e));
107     for (i = 0; i < r->num_elements; i++, e++)
108     {
109         Z_TaggedElement *t;
110
111         t = r->elements[i];
112         if (t->tagType)
113             e->tagType = *t->tagType;
114         else
115             e->tagType = 0;
116         e->tagWhich = t->tagValue->which;
117         if (t->tagValue->which == Z_StringOrNumeric_numeric)
118             e->tagVal.num = *t->tagValue->u.numeric;
119         else
120             ir_tcl_strdup (NULL, &e->tagVal.str, t->tagValue->u.string);
121         e->dataWhich = t->content->which;
122
123         switch (t->content->which)
124         {
125         case Z_ElementData_octets:
126             e->tagData.octets.len = t->content->u.octets->len;
127             e->tagData.octets.buf = ir_tcl_malloc (t->content->u.octets->len);
128             memcpy (e->tagData.octets.buf, t->content->u.octets->buf, 
129                     t->content->u.octets->len);
130             break;
131         case Z_ElementData_numeric:
132             e->tagData.num = *t->content->u.numeric;
133             break;
134         case Z_ElementData_date:
135             ir_tcl_strdup (NULL, &e->tagData.str, t->content->u.string);
136             break;            
137         case Z_ElementData_ext:
138             break;
139         case Z_ElementData_string:
140             ir_tcl_strdup (NULL, &e->tagData.str, t->content->u.string);
141             break;
142         case Z_ElementData_trueOrFalse:
143             e->tagData.bool = *t->content->u.trueOrFalse;
144             break;
145         case Z_ElementData_oid:
146             break;
147         case Z_ElementData_intUnit:
148             break;
149         case Z_ElementData_elementNotThere:
150         case Z_ElementData_elementEmpty:
151         case Z_ElementData_noDataRequested:
152             break;
153         case Z_ElementData_diagnostic:
154             break;
155         case Z_ElementData_subtree:
156             ir_tcl_grs_mk (t->content->u.subtree, &e->tagData.sub);
157             break;
158         }
159     }
160 }
161
162 static int ir_tcl_get_grs_r (Tcl_Interp *interp, IrTcl_GRS_Record *grs_record,
163                              int argc, char **argv, int argno)
164 {
165     static char tmpbuf[32];
166     int i;
167     struct GRS_Record_entry *e = grs_record->entries;
168
169     for (i = 0; i<grs_record->noTags; i++, e++)
170     {
171         int yes = 0;
172         if (argno >= argc)
173             yes = 1;
174         else
175         {
176             const char *cp0 = argv[argno];
177             const char *cp1 = strchr (cp0, '.');
178
179             if (!cp1 || cp1-cp0 < 1)
180                 yes = 1;
181             else
182             {
183                 if (atoi(cp0) == e->tagType) 
184                 {
185                     if (e->tagWhich == Z_StringOrNumeric_numeric)
186                     {
187                         if (atoi (cp1+1) == e->tagVal.num)
188                             yes = 1;
189                     }
190                     else
191                     {
192                         if (!strcmp (cp1+1, e->tagVal.str))
193                             yes = 1;
194                     }
195                 }
196             }
197         }
198         if (!yes)
199             continue;
200         Tcl_AppendResult (interp, "{ ", NULL);
201         sprintf (tmpbuf, "%d", e->tagType);
202         Tcl_AppendElement (interp, tmpbuf);
203
204         if (e->tagWhich == Z_StringOrNumeric_numeric)
205         {
206             Tcl_AppendResult (interp, " numeric ", NULL);
207             sprintf (tmpbuf, "%d", e->tagVal.num);
208             Tcl_AppendElement (interp, tmpbuf);
209         }
210         else
211         {
212             Tcl_AppendResult (interp, " string ", NULL);
213             Tcl_AppendElement (interp, e->tagVal.str);
214         }
215         switch (e->dataWhich)
216         {
217         case Z_ElementData_octets:
218             Tcl_AppendResult (interp, " octets {} ", NULL);
219             break;
220         case Z_ElementData_numeric:
221             Tcl_AppendResult (interp, " numeric ", NULL);
222             sprintf (tmpbuf, "%d", e->tagData.num);
223             Tcl_AppendElement (interp, tmpbuf);
224             break;
225         case Z_ElementData_date:
226             Tcl_AppendResult (interp, " date {} ", NULL);
227             break;
228         case Z_ElementData_ext:
229             Tcl_AppendResult (interp, " ext {} ", NULL);
230             break;
231         case Z_ElementData_string:
232             Tcl_AppendResult (interp, " string ", NULL);
233             Tcl_AppendElement (interp, e->tagData.str);
234             break;
235         case Z_ElementData_trueOrFalse:
236             Tcl_AppendResult (interp, " bool ",
237                               e->tagData.bool ? "1" : "0", " ", NULL);
238             break;
239         case Z_ElementData_oid:
240             Tcl_AppendResult (interp, " oid {} ", NULL);
241             break;
242         case Z_ElementData_intUnit:
243             Tcl_AppendResult (interp, " intUnit {} ", NULL);
244             break;
245         case Z_ElementData_elementNotThere:
246             Tcl_AppendResult (interp, " notThere {} ", NULL);
247             break;
248         case Z_ElementData_elementEmpty:
249             Tcl_AppendResult (interp, " empty {} ", NULL);
250             break;
251         case Z_ElementData_noDataRequested:
252             Tcl_AppendResult (interp, " notRequested {} ", NULL);
253             break;
254         case Z_ElementData_diagnostic:
255             Tcl_AppendResult (interp, " diagnostic {} ", NULL);
256             break;
257         case Z_ElementData_subtree:
258             Tcl_AppendResult (interp, " subtree { ", NULL);
259             ir_tcl_get_grs_r (interp, e->tagData.sub, argc, argv, argno+1);
260             Tcl_AppendResult (interp, " } ", NULL);
261             break;
262         }
263         Tcl_AppendResult (interp, " } ", NULL);
264     }
265     return TCL_OK;
266 }
267
268 int ir_tcl_get_grs (Tcl_Interp *interp, IrTcl_GRS_Record *grs_record, 
269                      int argc, char **argv)
270 {
271     return ir_tcl_get_grs_r (interp, grs_record, argc, argv, 3);
272 }
273