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