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