1 |
/* |
2 |
The Malete project - the Z39.2/Z39.50 database framework of OpenIsis. |
3 |
Version 0.9.x (patchlevel see file Version) |
4 |
Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org |
5 |
|
6 |
This library is free software; you can redistribute it and/or |
7 |
modify it under the terms of the GNU Lesser General Public |
8 |
License as published by the Free Software Foundation; either |
9 |
version 2.1 of the License, or (at your option) any later version. |
10 |
|
11 |
This library is distributed in the hope that it will be useful, |
12 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
14 |
See the GNU Lesser General Public License for more details. |
15 |
|
16 |
You should have received a copy of the GNU Lesser General Public |
17 |
License along with this library; if not, write to the Free Software |
18 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
|
20 |
see README for more information |
21 |
EOH */ |
22 |
|
23 |
/* |
24 |
$Id: pw.c,v 1.7 2004/03/29 09:35:20 kripke Exp $ |
25 |
Malete patchwork functions |
26 |
*/ |
27 |
|
28 |
#include "../pw/pw.h" |
29 |
|
30 |
|
31 |
Ses *ses; |
32 |
|
33 |
|
34 |
/* ************************************************************ |
35 |
object |
36 |
*/ |
37 |
|
38 |
int OPT_STDCALL mPipe ( Obj *self, Msg msg ) |
39 |
{ |
40 |
#if 1 |
41 |
(void)self; (void)msg; return ERR_INVAL; |
42 |
#else |
43 |
int rv = ERR_INVAL, eflg = env.flg; |
44 |
const char *p, *q, *e; |
45 |
Sink l1, l2, *pin, *pout, *eout = env.out; |
46 |
lInit( pout = &l1, 0 ); |
47 |
lInit( pin = &l2, 0 ); |
48 |
lCpy( pin, msg, 0 ); |
49 |
LADD( pout, -1, msg->val, msg->len ); |
50 |
env.out = pout; |
51 |
env.flg |= ENV_BUFFER; |
52 |
for ( p = msg->val, q = 0, e = msg->val + msg->len; e > p; ) { |
53 |
if ( ( TAB == *p++ && ( '|' == *p || msg->val == p-2 ) ) || e == p ) { |
54 |
if ( q ) { |
55 |
char *s = pin->fld->val; |
56 |
pin->fld->val += q - msg->val; |
57 |
pin->fld->len = ( p - q ); |
58 |
if ( e > p ) |
59 |
--pin->fld->len; |
60 |
if ( ( rv = self->snd( self, pin->fld ) ) ) |
61 |
goto cleanup; |
62 |
pin->fld->val = s; |
63 |
pin->fld->len = msg->len; |
64 |
lReset( pin ); |
65 |
env.out = pin; |
66 |
pin = pout; |
67 |
pout = env.out; |
68 |
} |
69 |
q = '|' == *p ? p+1 : p; |
70 |
} |
71 |
} |
72 |
LCPY( eout, pin ); |
73 |
cleanup: |
74 |
env.out = eout; |
75 |
env.flg = eflg; |
76 |
lClr( pin ); |
77 |
lClr( pout ); |
78 |
return rv; |
79 |
#endif |
80 |
} /* mPipe */ |
81 |
|
82 |
|
83 |
int OPT_STDCALL mComp ( Obj *self, Msg msg ) |
84 |
{ |
85 |
const char *e = msg->val + msg->len; |
86 |
char *q, *p; |
87 |
int rv = ERR_INVAL; |
88 |
for ( q = 0, p = msg->val, e = msg->val + msg->len; e > p; ) { |
89 |
if ( ( TAB == *p++ && ( ';' == *p || msg->val == p-2 ) ) || e == p ) { |
90 |
if ( q ) { |
91 |
msg->val = q; |
92 |
msg->len = (p - q); |
93 |
if ( e > p ) |
94 |
--msg->len; |
95 |
if ( 0 > (rv = self->snd(self, msg)) ) |
96 |
return rv; |
97 |
} |
98 |
q = ';' == *p ? p+1 : p; |
99 |
} |
100 |
} |
101 |
return rv; |
102 |
} /* mComp */ |
103 |
|
104 |
|
105 |
int OPT_STDCALL mComm ( Obj *self, Msg msg ) |
106 |
{ |
107 |
EADDF(msg); |
108 |
if ( -1 <= msg->tag ) |
109 |
return 0; |
110 |
if ( msg[1].tag > msg->tag+1 ) /* not properly embedded */ |
111 |
msg[1].tag = msg->tag+1; |
112 |
return self->snd(self, msg+1); |
113 |
} /* mComm */ |
114 |
|
115 |
|
116 |
int OPT_STDCALL oObj ( Obj *self, Msg msg ) |
117 |
{ |
118 |
eRr(LOG_VERBOSE, "oObj '%.*s'", msg->len, msg->val); |
119 |
if ( msg->len ) |
120 |
switch (*msg->val) { |
121 |
case '|': return mPipe(self, msg); |
122 |
case ';': return mComp(self, msg); |
123 |
case '#': return mComm(self, msg); |
124 |
case '=': return 0; |
125 |
case '.': return dispatch(msg); |
126 |
} |
127 |
else |
128 |
return eOut(0, "#\t0"); |
129 |
return eRr(ERR_INVAL, "unrecognized message '%.*s'", msg->len, msg->val); |
130 |
} /* oObj */ |
131 |
|
132 |
|
133 |
|
134 |
/* ************************************************************ |
135 |
struct |
136 |
*/ |
137 |
int OPT_STDCALL oStruct ( Struct *self, Msg msg ) |
138 |
{ |
139 |
HEntry *he; |
140 |
int nlen; |
141 |
char *p = msg->val, *e = p + msg->len; |
142 |
if ( !msg->len || CT_A != lat1ct[(unsigned char)*p] ) |
143 |
return oObj((Obj*)self, msg); |
144 |
eRr(LOG_VERBOSE, "oStruct '%.*s'", msg->len, msg->val); |
145 |
/* must address child */ |
146 |
for ( ;p < e; p++ ) |
147 |
switch (*p) { |
148 |
case TAB: |
149 |
break; |
150 |
case '.': |
151 |
goto dot; |
152 |
} |
153 |
return eRr(ERR_INVAL, "bad struct msg '%.*s'", p-msg->val, msg->val); |
154 |
dot: |
155 |
nlen = p++ - msg->val; |
156 |
if ( !self->reg || !(he = hGet(self->reg, msg->val, nlen)) ) { |
157 |
Obj *cld; |
158 |
if ( !self->fac || !(cld = self->fac(self, msg->val, nlen)) ) |
159 |
return ERR_INVAL; |
160 |
if ( !self->reg ) { |
161 |
self->reg = (HTable *) mAlloc( sizeof(HTable) ); |
162 |
hInit(self->reg, "reg"); |
163 |
} |
164 |
he = hSet(self->reg, msg->val, nlen, cld); |
165 |
} |
166 |
if ( he && he->obj ) { |
167 |
msg->len -= nlen + 1; |
168 |
msg->val = p; |
169 |
return ((Obj *) he->obj)->snd( (Obj *) he->obj, msg ); |
170 |
} |
171 |
return eRr(ERR_INVAL, "no such child '%.*s'", nlen, msg->val); |
172 |
} /* oStruct */ |
173 |
|
174 |
|
175 |
int OPT_STDCALL oSes ( Ses *self, Msg msg ) |
176 |
{ |
177 |
self->req++; |
178 |
if ( msg->len && '.' == *msg->val ) { /* rooted */ |
179 |
msg->val++; |
180 |
msg->len--; |
181 |
} else if (self->at) { /* prepend default */ |
182 |
/* TODO */ |
183 |
} |
184 |
return oStruct((Struct*)self, msg); |
185 |
} /* oSes */ |
186 |
|
187 |
|
188 |
Obj* OPT_STDCALL facMain ( Ses *self, const char *key, int len ) |
189 |
{ |
190 |
char *name = mDupz(key, len); |
191 |
Obj *ret; |
192 |
|
193 |
eRr(LOG_VERBOSE, "facMain '%.*s'", len, key); |
194 |
(void)self; /* could be used for authorization etc. */ |
195 |
/* we should scan env.opt for defined objects like remote servers |
196 |
however, db is the default anyway |
197 |
*/ |
198 |
ret = (Obj*)newDbo(name); |
199 |
mFree(name); |
200 |
return ret; |
201 |
} /* facMain */ |
202 |
|
203 |
|
204 |
void sInit (Ses *self) |
205 |
{ |
206 |
memset(self, 0, sizeof(Ses)); |
207 |
self->snd = (disp*)oSes; |
208 |
self->fac = (factory*)facMain; |
209 |
self->out = env.out; |
210 |
self->err = env.err; |
211 |
/* TODO: check env opts for option settings */ |
212 |
self->r = 20; |
213 |
self->q = 20; |
214 |
self->s = 10000; |
215 |
} /* sInit */ |