2 Syren -- a lightweight downloader for Linux/BSD/MacOSX
3 inspired by Axel Copyright 2001-2002 Wilmer van der Gaast
4 version 0.0.6 (atomic alien)
5 coded by Ketmar // Avalon Group
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License with
18 the Debian GNU/Linux distribution in file /usr/doc/copyright/GPL;
19 if not, write to the Free Software Foundation, Inc., 59 Temple Place,
20 Suite 330, Boston, MA 02111-1307 USA
23 Syren scripting engine
25 #ifndef _SYREN_SCRIPT_C
26 #define _SYREN_SCRIPT_C
30 #include "syren_common.h"
31 #include "syren_str.h"
32 #include "syren_msg.h"
33 #include "syren_hdrs.h"
34 #include "syren_script.h"
37 char *SyLoadWholeFile (const char *fname
) {
44 if (!fname
|| !fname
[0]) return NULL
;
45 if (!strcmp(fname
, "-")) {
47 sz
= 1024; res
= malloc(sz
); if (!res
) return NULL
;
48 *res
= '\0'; p
= res
; left
= sz
-1;
50 rd
= read(fd
, p
, left
);
51 if (rd
<= 0) return res
;
54 if (sz
> 2*1024*1024) p
= NULL
; else p
= realloc(res
, sz
);
55 if (!p
) { free(res
); return NULL
; }
56 res
= p
; p
= p
+strlen(p
); left
= sz
-(p
-res
)-1;
59 int fd
= SyOpenFile(fname
, SY_FMODE_READ
, SY_FALSE
);
60 if (fd
< 0) return NULL
;
62 if (sz
> 0 || sz
<= 4*1024*1024) {
63 res
= calloc(1, sz
+1);
65 if (SyReadFile(fd
, res
, sz
) != SY_OK
) { free(res
); res
= NULL
; }
75 #ifdef SYREN_USE_SCRIPT
76 TSyBool syScriptOK
= SY_FALSE
;
79 static const TSyPrintStr
*xpfn
= NULL
;
82 static char *resstr
= NULL
;
84 void KLispPrintF (const char *fmt
, ...) {
89 if ((p
= malloc(size
)) == NULL
) return;
93 n
= vsnprintf(p
, size
, fmt
?fmt
:"", ap
);
95 if (n
> -1 && n
< size
) break;
96 if (n
> -1) size
= n
+1; else size
*= 2;
97 if ((np
= realloc(p
, size
)) == NULL
) { free(p
); return; }
101 np
= SySPrintf("%s%s", resstr
?resstr
:"", p
);
107 /*fprintf(stderr, "!!!%s!!!\n", resstr);*/
108 while ((p
= strchr(resstr
, '\n'))) {
110 if (xpfn
) SyMessage(xpfn
, SY_MSG_MSG
, "%s", resstr
);
111 p
++; np
= resstr
; while ((*np
++ = *p
++)) ;
113 if (!*resstr
) { free(resstr
); resstr
= NULL
; }
117 static void KLispFlush (void) {
118 if (xpfn
&& resstr
&& *resstr
) SyMessage(xpfn
, SY_MSG_MSG
, "%s", resstr
);
119 if (resstr
) { free(resstr
); resstr
= NULL
; }
123 static int KLPrim_Load (KLISP_POOL_DEF
int args
) {
126 const char *sexpr
, *s
;
128 /*KLispPrintCell(KLISP_POOL_ARG args); KLispPrintF("\n");*/
129 if (!KLispCheckArgs(KLISP_POOL_ARG args
, 1, "$", "load", 1)) return 0;
130 s
= KLISP_CELL(KLISP_CELL(args
).car
).str
;
131 if (!*s
) return KLispError(KLISP_POOL_ARG
"load: invalid file name");
133 t
= SySPrintf("%s.lsp", s
);
134 if (!t
) goto errquit
;
135 str
= SyLoadWholeFile(t
);
136 if (str
) goto loaded
;
139 str
= getenv("HOME");
141 t
= SySPrintf("%s/.syren/%s.lsp", str
, s
);
142 if (!t
) goto errquit
;
143 str
= SyLoadWholeFile(t
);
144 if (str
) goto loaded
;
148 t
= SySPrintf("/etc/syren/%s.lsp", s
);
149 if (!t
) goto errquit
;
150 str
= SyLoadWholeFile(t
);
151 if (str
) goto loaded
;
154 return KLispError(KLISP_POOL_ARG
"file not found: %s.lsp", s
);
156 KLispPrintF("file: %s\n", t
);
157 sexpr
= str
; cell
= KLispParseSExpr(KLISP_POOL_ARG
&sexpr
);
159 if (KLISP_POOL
->error
) {
160 KLispPrintF("%s: PARSE ERROR: %s\n", t
, KLISP_POOL
->error
);
167 return KLispErrorMem(KLISP_POOL_ARG0
);
176 static void *KLCheckUType (KLISP_POOL_DEF
int args
, TUDataType ctype
) {
179 if (!args
) goto error
;
180 args
= KLISP_CELL(args
).car
;
181 if (!args
) goto error
;
182 if (KLISP_CELL(args
).ctype
!= KLISP_TYPE_UDATA
) goto error
;
183 ptr
= KLISP_CELL(args
).udata
;
184 if (*((TUDataType
*)ptr
) != ctype
) goto error
;
188 KLispError(KLISP_POOL_ARG
"invalid udata type");
200 static int KURLFinalizer (KLISP_POOL_DEF
void *ptr
, int udatacell
) {
201 /*fprintf(stderr, "finalizer for <%s>\n", ((TUDataURL *)ptr)->url);*/
213 int port; TSyBool defaultPort;
214 char *dir, *file, *query, *anchor;
217 #define XURL_MENTRY(name) \
218 {1, KURL_Get##name, "Get" #name}, \
219 {1, KURL_Set##name, "Set" #name},
221 #define XURL_SFIELD(name,fldname) \
222 static int KURL_Get##name (KLISP_POOL_DEF int args) {\
225 if (!KLispCheckArgs(KLISP_POOL_ARG args, 1, "u", "URL:Get" #name, 1)) return 0; \
226 if (!(uurl = KLCheckUType(KLISP_POOL_ARG args, UDATA_URL))) return 0; \
228 return KLispNewSym(KLISP_POOL_ARG uurl->url->fldname); \
230 static int KURL_Set##name (KLISP_POOL_DEF int args) { \
234 if (!KLispCheckArgs(KLISP_POOL_ARG args, 1, "u$", "URL:Set" #name, 1)) return 0; \
235 if (!(uurl = KLCheckUType(KLISP_POOL_ARG args, UDATA_URL))) return 0; \
236 args = KLISP_CELL(KLISP_CELL(args).cdr).car; \
237 s = SyStrDup(KLISP_CELL(args).str); \
239 SyStrFree(uurl->url->fldname); \
240 uurl->url->fldname = s; \
247 #define XURL_NFIELD(name,fldname) \
248 static int KURL_Get##name (KLISP_POOL_DEF int args) {\
251 if (!KLispCheckArgs(KLISP_POOL_ARG args, 1, "u", "URL:Get" #name, 1)) return 0; \
252 if (!(uurl = KLCheckUType(KLISP_POOL_ARG args, UDATA_URL))) return 0; \
254 return KLispNewNum(KLISP_POOL_ARG uurl->url->fldname); \
256 static int KURL_Set##name (KLISP_POOL_DEF int args) { \
259 if (!KLispCheckArgs(KLISP_POOL_ARG args, 1, "un", "URL:Set" #name, 1)) return 0; \
260 if (!(uurl = KLCheckUType(KLISP_POOL_ARG args, UDATA_URL))) return 0; \
261 args = KLISP_CELL(KLISP_CELL(args).cdr).car; \
262 uurl->url->fldname = (int)KLISP_CELL(args).num; \
268 XURL_SFIELD(Proto
, protostr
)
269 XURL_SFIELD(User
, user
)
270 XURL_SFIELD(Pass
, pass
)
271 XURL_SFIELD(Host
, host
)
272 XURL_SFIELD(Dir
, dir
)
273 XURL_SFIELD(File
, file
)
274 XURL_SFIELD(Query
, query
)
275 XURL_SFIELD(Anchor
, anchor
)
276 XURL_NFIELD(Port
, port
)
278 struct _TKLispPrimItem uURLMethods
[] = {
295 static int KLPrim_URL (KLISP_POOL_DEF
int args
) {
299 uurl
= calloc(1, sizeof(TUDataURL
));
300 uurl
->url
= state
->url
;
301 coURL
= KLispNewUData(KLISP_POOL_ARG uurl
, KURLFinalizer
);
302 if (coURL
< 0) { free(uurl
); return -1; }
303 if (!KLispRegisterMethods(KLISP_POOL_ARG coURL
, uURLMethods
)) {
313 / * return NULL or new string * /
314 char *SyHdrGetCookie (const TSyHdrs *hdr, const char *name);
315 void SyHdrDeleteCookie (TSyHdrs *hdr, const char *name);
318 extern TSyHdrs
*scHdrs
;
320 static int KLPrim_HdrGetField (KLISP_POOL_DEF
int args
) {
323 if (!KLispCheckArgs(KLISP_POOL_ARG args
, 1, "$", "HdrGetField", 1)) return 0;
324 if (!scHdrs
) return 0; /* no headers here */
325 val
= SyHdrGetFieldValue(scHdrs
, KLISP_CELL(KLISP_CELL(args
).car
).str
);
326 if (!val
) return 0; /* no such field */
327 args
= KLispNewSym(KLISP_POOL_ARG val
);
334 static int KLPrim_HdrSetField (KLISP_POOL_DEF
int args
) {
337 if (!KLispCheckArgs(KLISP_POOL_ARG args
, 1, "$[$N]", "HdrSetField", 1)) return 0;
338 if (!scHdrs
) return 0; /* no headers here */
339 arg1
= KLISP_CELL(args
).car
;
340 arg2
= KLISP_CAR_EX(KLISP_CDR_EX(args
));
342 if (SyHdrSetFieldValue(scHdrs
, KLISP_CELL(arg1
).str
, KLISP_CELL(arg2
).str
) != SY_OK
) return 0;
344 if (SyHdrDeleteField(scHdrs
, KLISP_CELL(arg1
).str
) != SY_OK
) return 0;
351 static int KLPrim_HdrGetCode (KLISP_POOL_DEF
int args
) {
352 if (!KLispCheckArgs(KLISP_POOL_ARG args
, 1, "", "HdrGetCode", 1)) return 0;
353 if (!scHdrs
) return 0; /* no headers here */
355 return KLispNewNum(KLISP_POOL_ARG scHdrs
->code
);
359 static int KLPrim_HdrSetCode (KLISP_POOL_DEF
int args
) {
360 if (!KLispCheckArgs(KLISP_POOL_ARG args
, 1, "n", "HdrSetCode", 1)) return 0;
361 if (!scHdrs
) return 0; /* no headers here */
362 scHdrs
->code
= (int)(KLISP_CELL(KLISP_CAR_EX(args
)).num
);
368 struct _TKLispPrimItem syKLispPrimList
[] = {
369 {1, KLPrim_Load
, "load"},
370 {1, KLPrim_URL
, "URL"},
371 {1, KLPrim_HdrGetField
, "HdrGetField"},
372 {1, KLPrim_HdrSetField
, "HdrSetField"},
373 {1, KLPrim_HdrGetCode
, "HdrGetCode"},
374 {1, KLPrim_HdrSetCode
, "HdrSetCode"},
380 static TKLispPool
*pool
= NULL
;
383 TSyResult
SyScriptInit (const TSyPrintStr
*pfn
) {
384 syScriptOK
= SY_FALSE
;
385 if (!(pool
= KLispNewPool())) {
386 SyMessage(pfn
, SY_MSG_WARNING
, "can't initialize scripting engine");
389 if (!KLispRegisterPrims(KLISP_POOL_ARG klispPrimList
)) {
390 SyMessage(pfn
, SY_MSG_WARNING
, "can't initialize scripting engine primitives");
391 KLispFreePool(KLISP_POOL_ARG0
);
394 if (!KLispRegisterPrims(KLISP_POOL_ARG syKLispPrimList
)) {
395 SyMessage(pfn
, SY_MSG_WARNING
, "can't initialize scripting engine primitives (1)");
396 KLispFreePool(KLISP_POOL_ARG0
);
399 syScriptOK
= SY_TRUE
;
405 void SyScriptDeinit (void) {
406 if (syScriptOK
!= SY_TRUE
) return;
407 KLispFreePool(KLISP_POOL_ARG0
);
409 syScriptOK
= SY_FALSE
;
413 static int Eval (KLISP_POOL_DEF
const char *str
, const TSyPrintStr
*pfn
) {
414 int optPrintParsed
= 0, optPrintResult
= 0, optPrintError
= 0;
417 KLispEvalStringEx(KLISP_POOL_ARG str
, &optPrintParsed
, &optPrintResult
, &optPrintError
);
420 if (KLISP_POOL
->error
) {
421 SyMessage(pfn
, SY_MSG_WARNING
, "script error: %s", KLISP_POOL
->error
);
429 TSyResult
SyScriptLoad (const char *fname
, TSyBool showNoFile
, const TSyPrintStr
*pfn
) {
432 if (syScriptOK
!= SY_TRUE
) return SY_ERROR
;
433 str
= SyLoadWholeFile(fname
);
435 if (showNoFile
== SY_TRUE
) SyMessage(pfn
, SY_MSG_WARNING
, "can't load script: %s", fname
?fname
:"()");
438 if (!Eval(KLISP_POOL_ARG str
, pfn
)) return SY_ERROR
;
444 void SyScriptLoadInit (const char *argv0
, const TSyPrintStr
*pfn
) {
447 if (syScriptOK
!= SY_TRUE
) return;
448 SyScriptLoad("/etc/syren/syren.lsp", SY_FALSE
, pfn
);
451 s
= SySPrintf("%s/.syren/syren.lsp", t
);
452 SyScriptLoad(s
, SY_FALSE
, pfn
);
454 s
= SySPrintf("%s/syren.lsp", t
);
455 SyScriptLoad(s
, SY_FALSE
, pfn
);
463 if (*t
== '/') l
= t
;
468 t
= SySPrintf("%s/syren.lsp", s
);
470 SyScriptLoad(t
, SY_FALSE
, pfn
);
477 SyScriptLoad("syren.lsp", SY_FALSE
, pfn
);
481 TSyResult
SyScriptCallback (const char *event
, const TSyPrintStr
*pfn
) {
484 cb
= KLispGetSymbol(KLISP_POOL_ARG event
);
485 if (cb
<= 0) return SY_OK
;
488 /*KLispPrintCell(KLISP_POOL_ARG cb);
490 KLispFreeError(KLISP_POOL_ARG0
);
491 cb
= KLispNewCons(KLISP_POOL_ARG
KLISP_CELL(cb
).cdr
, 0);
492 /*KLispPrintCell(KLISP_POOL_ARG cb);
494 if (cb
>= 0) KLispEval(KLISP_POOL_ARG cb
, NULL
, NULL
);
497 if (KLISP_POOL
->error
) {
498 SyMessage(pfn
, SY_MSG_WARNING
, "script error: %s", KLISP_POOL
->error
);