Bug fix: memory used by GRS records wasn't freed.
[ir-tcl-moved-to-github.git] / queue.c
1
2 /*
3  * IR toolkit for tcl/tk
4  * (c) Index Data 1995
5  * See the file LICENSE for details.
6  * Sebastian Hammer, Adam Dickmeiss
7  *
8  * $Log: queue.c,v $
9  * Revision 1.8  1996-03-05 09:21:20  adam
10  * Bug fix: memory used by GRS records wasn't freed.
11  * Rewrote some of the error handling code - the connection is always
12  * closed before failback is called.
13  * If failback is defined the send APDU methods (init, search, ...) will
14  * return OK but invoke failback (as is the case if the write operation
15  * fails).
16  * Bug fix: ref_count in assoc object could grow if fraction of PDU was
17  * read.
18  *
19  * Revision 1.7  1996/02/19  15:41:55  adam
20  * Better log messages.
21  * Minor improvement of connect method.
22  *
23  * Revision 1.6  1996/02/06  09:22:54  adam
24  * Ported ir-tcl to use beta releases of tcl7.5/tk4.1.
25  *
26  * Revision 1.5  1995/11/28  13:53:40  quinn
27  * Windows port.
28  *
29  * Revision 1.4  1995/10/17  12:18:59  adam
30  * Bug fix: when target connection closed, the connection was not
31  * properly reestablished.
32  *
33  * Revision 1.3  1995/08/04  11:32:40  adam
34  * More work on output queue. Memory related routines moved
35  * to mem.c
36  *
37  * Revision 1.2  1995/08/03  13:23:01  adam
38  * Request queue.
39  *
40  * Revision 1.1  1995/07/28  10:28:39  adam
41  * First work on request queue.
42  *
43  */
44
45 #include <stdlib.h>
46 #include <stdio.h>
47 #include <ctype.h>
48 #include <assert.h>
49
50 #include "ir-tclp.h"
51
52 int ir_tcl_send_APDU (Tcl_Interp *interp, IrTcl_Obj *p, Z_APDU *apdu,
53                       const char *msg, const char *object_name)
54 {
55     IrTcl_Request **rp;
56
57     if (!z_APDU (p->odr_out, &apdu, 0))
58     {
59         Tcl_AppendResult (interp, odr_errmsg (odr_geterror (p->odr_out)),
60                           NULL);
61         odr_reset (p->odr_out);
62         return TCL_ERROR;
63     }
64     rp = &p->request_queue;
65     while (*rp)
66         rp = &(*rp)->next;
67     *rp = ir_tcl_malloc (sizeof(**rp));
68     (*rp)->next = NULL;
69     
70     if (ir_tcl_strdup (interp, &(*rp)->object_name, object_name) == TCL_ERROR)
71         return TCL_ERROR;
72     if (ir_tcl_strdup (interp, &(*rp)->callback, p->callback) == TCL_ERROR)
73         return TCL_ERROR;
74     
75     (*rp)->buf_out = odr_getbuf (p->odr_out, &(*rp)->len_out, NULL);
76     odr_setbuf (p->odr_out, NULL, 0, 1);
77     odr_reset (p->odr_out);
78     if (p->state == IR_TCL_R_Idle)
79     {
80         logf (LOG_DEBUG, "send_apdu. Sending %s", msg);
81         if (ir_tcl_send_q (p, p->request_queue, msg) == TCL_ERROR)
82         {
83             if (p->failback)
84             {
85                 ir_tcl_disconnect (p);
86                 p->failInfo = IR_TCL_FAIL_WRITE;
87                 ir_tcl_eval (interp, p->failback);
88                 return TCL_OK;
89             }
90             else 
91             {
92                 sprintf (interp->result, "cs_put failed in %s", msg);
93                 return TCL_ERROR;
94             }
95         } 
96     }
97     else
98         logf (LOG_DEBUG, "send_apdu. Not idle (%s)", msg);
99     return TCL_OK;
100 }
101
102 int ir_tcl_send_q (IrTcl_Obj *p, IrTcl_Request *rp, const char *msg)
103 {
104     int r;
105
106     assert (rp);
107     r = cs_put (p->cs_link, rp->buf_out, rp->len_out);
108     if (r < 0)
109         return TCL_ERROR;
110     else if (r == 1)
111     {
112 #if IRTCL_GENERIC_FILES
113         ir_select_add_write (p->csFile, p);
114 #else
115         ir_select_add_write (cs_fileno (p->cs_link), p);
116 #endif
117         logf (LOG_DEBUG, "Send part of %s", msg);
118         p->state = IR_TCL_R_Writing;
119     }
120     else
121     {
122         logf (LOG_DEBUG, "Send %s (%d bytes) fd=%d", msg, rp->len_out,
123               cs_fileno(p->cs_link));
124         p->state = IR_TCL_R_Waiting;
125         free (rp->buf_out);
126         rp->buf_out = NULL;
127     }
128     return TCL_OK;
129 }
130
131 void ir_tcl_del_q (IrTcl_Obj *p)
132 {
133     IrTcl_Request *rp, *rp1;
134
135     p->state = IR_TCL_R_Idle;
136     for (rp = p->request_queue; rp; rp = rp1)
137     {
138         free (rp->object_name);
139         free (rp->callback);
140         free (rp->buf_out);
141         rp1 = rp->next;
142         free (rp);
143     }
144     p->request_queue = NULL;
145 }
146
147
148