1 |
dpavlin |
604 |
/* |
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 */ |