Author SHA1 Message Date
fred b6bea78591 feat: release alpha-8 2026-07-14 10:19:52 +02:00
fred 0445f10ebe WIP VAR_PARAM management 2026-06-28 18:01:09 +02:00
fred ad317a2070 feat: ssh_lib, VAR_PARAM management (when hashtable element) 2026-06-28 16:12:04 +02:00
fred e0eaf6f9e8 WIP exception bubbling 2026-06-14 18:14:25 +02:00
fred b70cee802b WIP exception bubbling
WIP ssh lib
2026-06-14 15:45:35 +02:00
11 changed files with 932 additions and 46 deletions

No files matched your search

+3
View File
@@ -414,6 +414,7 @@ int assembler(env * e, char * fichier, int * cptLig, int compress)
case IN_SELE:
case IN_RNXT:
case IN_CPHA:
case IN_CPHH:
// PVAT / TYPO / PSHT / SELE / RNXT / CPHA
PCODE(instr);
break;
@@ -1086,6 +1087,8 @@ int disassembler(env * e, char * fichier)
// RNXT
case IN_CPHA:
// CPHA
case IN_CPHH:
// CPHJ
case IN_PSHV:
// PSHV
case IN_POPV:
+4
View File
@@ -27,6 +27,10 @@ echo 3b. Compilation de securesockMod.c
gcc -shared -s -o exec/securesock_lib.so w_src/securesock_lib.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -lssl -lcrypto -l:sock_lib.so
gcc -shared -s -o exec/securesock.o w_src/securesockMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -l:securesock_lib.so
echo 3c. Compilation de sshMod.c
gcc -shared -s -o exec/wssh_lib.so w_src/ssh_lib.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -lssl -lcrypto -lssh
gcc -shared -s -o exec/wssh.o w_src/sshMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -l:wssh_lib.so
#echo 4. Compilation de sqlite
#gcc -shared -s -o exec/db.o w_src/dbMod.c -m64 -DUNIX -Wall -ldl -fPIC -L./exec -l:libw.so
#gcc -shared -s -o exec/pgsql.o w_src/dbpgsql.c -m64 -DUNIX -Wall -I/usr/include/postgresql -fPIC -L./exec -l:libw.so
+4
View File
@@ -58,6 +58,10 @@ echo 2eb. Compilation de securesockMod.c
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\securesock_lib.dll w_src\securesock_lib.c exec\libw.lib exec\sock_lib.lib ws2_32.lib /DEBUG:NONE /I"C:\Users\Poupougne42\source\vcpkg-master\installed\x64-windows/include" /link /LIBPATH:"C:\Users\Poupougne42\source\vcpkg-master\installed\x64-windows\lib" libssl.lib libcrypto.lib
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\securesock.dll w_src\securesockMod.c exec\libw.lib exec\sock_lib.lib exec\securesock_lib.lib ws2_32.lib /DEBUG:NONE /I"C:\Users\Poupougne42\source\vcpkg-master\installed\x64-windows/include"
echo 2ec. Compilation de sshMod.c
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\wssh_lib.dll w_src\ssh_lib.c exec\libw.lib ws2_32.lib /DEBUG:NONE /I"C:\Users\Poupougne42\source\vcpkg-master\installed\x64-windows/include" /link /LIBPATH:"C:\Users\Poupougne42\source\vcpkg-master\installed\x64-windows\lib" ssh.lib libssl.lib libcrypto.lib z.lib
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\wssh.dll w_src\sshMod.c exec\libw.lib exec\wssh_lib.lib ws2_32.lib /DEBUG:NONE /I"C:\Users\Poupougne42\source\vcpkg-master\installed\x64-windows/include" /link /LIBPATH:"C:\Users\Poupougne42\source\vcpkg-master\installed\x64-windows\lib" ssh.lib libssl.lib libcrypto.lib z.lib
echo 2f. Compilation de convMod.c
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\conv.dll w_src\convMod.c exec\libw.lib /DEBUG:NONE
+2 -1
View File
@@ -64,7 +64,8 @@ char * strerr[] = {
"EX_SORTEDSEARCH_KO sort type incorrect",
"EX_SQRT_NEG square root of a negative number is not calculated.",
"EX_INT_EXP Fractional exponentiation is not calculated",
"EX_VARPARAM_KO Null parameter pointer"
"EX_VARPARAM_KO Null parameter pointer",
"EX_PARAM_NOTFOUND Named parameter not found"
};
enum {
+15 -3
View File
@@ -103,6 +103,7 @@ Dynamic forend,forinc; /* variables pour le code asm des boucles foreach numeri
Dynamic varparam; /* contient les variables passees en parametre a une sub : interdire ceratins formes d'appel pour eviter plus tard des erreurs de pointeur */
int doVarParam; /* booleen pour activer dans variable() la memo des variables dans varparam */
int derPvah; /* dans un passage de parametre, indique si la derniere operation PVAR/PVAH/PVAI est bien PVAH */
int typeof_; /* gestion du cas "typeof var" dans terme() */
@@ -458,10 +459,14 @@ long variable(env * e, Dynamic * resultat, Dynamic * valex, Dynamic * tmp, Dynam
else
{
if(tok == r.identsep)
{
dynConcatSz(e, resultat, "PVAH ", 5);
derPvah = 1;
}
else
{
dynConcatSz(e, resultat, "PVAI ", 5);
derPvah = 0;
if(doVarParam)
doVarParam = 2; // indique au moins une indirection dans les vars
}
@@ -2220,6 +2225,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
{
dynSetLen(e, &trav, 0);
aGauche = 0;
derPvah = 0;
if(variable(e, &trav, valex, tmp, encours, &aGauche) == VAR_ERR)
{
doVarParam = 0;
@@ -2227,7 +2233,13 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
printf("Erreur ligne %dc%s : parametre do/call/invoke incorrect\n", numlig, tmp->mPtr);
return DYN_ERR; /* TODO numeroter les erreurs */
}
dynConcatSz(e, &trav, "CPHA", DYN_LGNONE);
if(derPvah)
{
int np = dynDcount(e, &trav, '\n', DYN_NONE, DYN_NONE);
if(np >= 3)
dynInsSz(e, &trav, np - 1, DYN_NONE, "SADV", 4, '\n', DYN_NONE);
}
dynConcatSz(e, &trav, derPvah ? "CPHH" : "CPHA", DYN_LGNONE);
dynIns(e, &envers, 1, DYN_NONE, &trav, '\n', DYN_NONE);
if(tok == r.endpar)
break;
@@ -2578,7 +2590,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
dynConcat(e, resultat, &envers);
if(setfld == 0)
{
// TODO var[] DESV DESH DESI
// var[] DESV DESH DESI
if(aGauche != 2)
dynConcatSz(e, resultat, "DESV\n", 5); // une seule var a gauche DESV
else
@@ -2592,7 +2604,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
}
else
{
// TODO var{}[] DEZV DEZH DEZI
// var{}[] DEZV DEZH DEZI
if(aGauche != 2)
dynConcatSz(e, resultat, "DEZV\n", 5); // une seule var a gauche DEZV
else
+3 -1
View File
@@ -48,7 +48,7 @@ char libInstr[256 * 4] ={"VERS" "JUMP" "DECL" "SRCL" "BEXC" "EXCE" "CATC" "THRW"
"FMTA" "INSE" "REMV" "TONU" "TOST" "CCAT" "SSTR" "SSEP" "FLDF" "FLDS" /* 0-99 */
"DCOS" "FMTT" "FMTS" "SCHS" "INSS" "REMS" "DEXH" "DEXI" "PREC" "DESV"
"DESH" "DESI" "DEZV" "DEZH" "DEZI" "SDBG" "PHDN" "PIDN" "SADV" "VLET" /* 110-119 */
"PHDV" "PIDV" "HCOU" "PVHD" "PVID" "SSRC" "SSCS" "xxxx" "xxxx" "xxxx" /* 126 */
"PHDV" "PIDV" "HCOU" "PVHD" "PVID" "SSRC" "SSCS" "CPHH" "xxxx" "xxxx" /* 127 */
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
@@ -330,6 +330,8 @@ char libComp[10 * 3] = {"EQ " "NE " "LT " "GT " "LE " "GE " "AND" "OR " "NOT" "F
#define IN_SSRC 125
#define IS_SSCS "\x7E"
#define IN_SSCS 126
#define IS_CPHH "\x7F"
#define IN_CPHH 127
#define IS_PROG "\xFA"
#define IN_PROG 250
+217 -39
View File
@@ -256,6 +256,89 @@ void cpop(env * e, var * v)
}
}
void cpushex(env * e, var * v)
{
if(e != NULL && v != NULL && v->type == VAR_PARAM)
{
/* ok pour empiler */
e->call_stack.write = e->call_stack.read + sizeof(entry);
if(e->call_stack.read >= e->call_stack.lgmax || e->call_stack.write > e->call_stack.lgmax)
{
/* depassement capacite buffer */
e->exception = EX_BUFOVF;
return;
}
else
{
entry ent;
ent.content = *v;
ent.nom1 = e->nom64[0];
ent.nom2 = e->nom64[1];
ent.nom3 = e->nom64[2];
*((entry *)(e->call_stack.ptr + e->call_stack.read)) = ent;
e->call_stack.read = e->call_stack.write;
}
}
}
void cpopex(env * e, var * v)
{
if(e != NULL && v != NULL)
{
/* ok pour depiler */
if(e->call_stack.read < sizeof(entry))
{
/* depassement capacite buffer */
e->exception = EX_BUFOVF;
return;
}
else
{
if(e->nom64[0] == 0 && e->nom64[1] == 0 && e->nom64[2] == 0)
{
/* pas de nom : depiler a la position courante */
e->call_stack.read -= sizeof(entry);
*v = ((entry *)(e->call_stack.ptr + e->call_stack.read))->content; /* raz position lue ? */
}
else
{
/* parametre affecte a un nom de variable : le chercher, si trouve le renvoyer et swap avec la position courante,
si pas trouve : si tous les content n'ont pas de nom, depiler a la position courante, sinon exception */
entry w;
ent64 posRead = e->call_stack.read - sizeof(entry);
ent64 posReadTop = posRead;
int nbAvecNom = 0;
for( ;posRead >= 0; posRead -= sizeof(entry))
{
w = *(entry *)(e->call_stack.ptr + posRead);
if(w.nom1 == e->nom64[0] && w.nom2 == e->nom64[1] && w.nom3 == e->nom64[2])
{
/* trouve */
*v = w.content;
e->call_stack.read -= sizeof(entry);
if(posRead < posReadTop)
/* trouve a une position plus basse : swap avec la position courante (sinon raf) */
*(entry *)(e->call_stack.ptr + posRead) = *(entry *)(e->call_stack.ptr + posReadTop);
return;
}
if(w.nom1 != 0 || w.nom2 != 0 || w.nom3 != 0)
nbAvecNom++;
}
/* pas trouve : si aucun nom donne dans la pile, depiler a la position courante (non regression version precedente), sinon exception */
if(nbAvecNom == 0)
{
e->call_stack.read -= sizeof(entry);
*v = ((entry *)(e->call_stack.ptr + e->call_stack.read))->content;
}
else
{
e->exception = EX_PARAM_NOTFOUND;
}
}
}
}
}
void craz(env * e)
{
/* remet la call stack "vide" */
@@ -277,6 +360,17 @@ void callstack_printdebug(env * e)
}
}
void callstack_printdebug_ex(env * e)
{
printf("call_stack read=%lld lgmax=%lld\n", e->call_stack.read, e->call_stack.lgmax);
for(e->call_stack.write = e->call_stack.read; e->call_stack.write > 0; )
{
e->call_stack.write -= sizeof(entry);
printf(" %03lld > ", e->call_stack.write);
var_printdebug(e, &((entry *)(e->call_stack.ptr + e->call_stack.write))->content, "");
}
}
#ifdef numstack
/* empilage/depilage num stack : number - obsolete */
#else
@@ -2138,7 +2232,7 @@ void instr_trace(env * e)
}
/* ********************************************************** */
// TODO pour les instr > 1 octet, verifier "e->si" avant chaque lecture de parametre
// pour les instr > 1 octet, verifier "e->si" avant chaque lecture de parametre
void instr_000(env * e)
{
/* VERS */
@@ -2240,18 +2334,18 @@ void instr_007(env * e)
/* => mecanisme realise dans la fonction "decode" */
}
/* */
void NewProcess(env * e, var * prog); // TODO a enlever ensuite !!!!
//void NewProcess(env * e, var * prog); // TODO a enlever ensuite !!!!
void instr_008(env * e)
{
/* PART */
if(e->si > e->fin) { e->exception = EX_END; return; }
e->part = lire8(e->si++);
/* definit la region/partie du code en cours */
// TEST a enlever !!! TODO
/* TEST a enlever !!! TODO
dynLet(e, &e->int_dynamic, "calc", 4);
printf("part: %d\n", e->part);
if(e->part == 255)
NewProcess(e, &e->int_dynamic);
NewProcess(e, &e->int_dynamic);*/
}
/* */
void instr_009(env * e)
@@ -2684,6 +2778,7 @@ void instr_024(env * e)
// les variable de la call stack sont deja toutes des pointeurs (VAR_PARAM)
var param1, param2, param3;
var * p1 = NULL, * p2 = NULL, * p3 = NULL;
e->nom64[0] = 0; e->nom64[1] = 0; e->nom64[2] = 0;
cpop(e, &param1); // seule exception possible ici : EX_BUFOVF car pas/plus de parametre empile
if(!e->exception) p1 = &param1;
cpop(e, &param2);
@@ -2779,6 +2874,7 @@ void instr_028(env * e)
return;
}
if(e->ad_var->type == VAR_PARAM)
{
if((e->ad_var = (var *)e->ad_var->ptr) == NULL) /* travailler avec la var pointee ! */
{
e->exception = EX_VARPARAM_KO;
@@ -2789,6 +2885,7 @@ void instr_028(env * e)
}
return;
}
}
/* */
if(e->mode_typeof)
{
@@ -2946,7 +3043,7 @@ void instr_032(env * e)
if(e->exception != OK)
return;
if(e->ad_var->type == VAR_PARAM)
e->ad_var = (var *)e->ad_var->ptr; /* travailler avec la var pointee, controle deja fait avant : ras ici */
e->ad_var = (var *)e->ad_var->ptr; /* travailler avec la var pointee, controle deja fait avant (var_free) : ras ici */
var_init(e, e->ad_var, VAR_DYNAMIC, 0, lg, NULL);
if(lg > 0)
{
@@ -3265,10 +3362,29 @@ void instr_040(env * e)
e->exception = EX_NOADVAR;
return;
}
/* TODO : si sub, ok, si class, ne pas faire ?? */
/* suppression variable "simple" (que PVAR : locale ou globale) => mis en VARNULL, idem declare */
var * v = &e->v;
e->v.type = VAR_NULL;
if(e->ad_var->type == VAR_PARAM)
{
/* cas particulier si param sur hash : suppression reelle a faire (et PAS PVHD/PVID dans ce cas ici) */
if(e->ad_var->ptr == NULL)
{
e->exception = EX_VARPARAM_KO;
return;
}
if(e->ad_var->etat != NULL)
{
/* appartient a une hash : supprimer de la hash et RAZ pointeur (VAR_PARAM plus utilisable) */
var_free(e, e->ad_var, TRUE);
((var *)(e->ad_var->ptr))->type = 0;
ent64 * ent = (ent64 *)(e->ad_var->ptr - 3 * sizeof(ent64));
*ent++ = 0; *ent++ = 0; *ent = 0;
e->ad_var->ptr = NULL;
return;
}
/* n'appartient pas a une hash, variable "simple" : forcer la var a VAR_NULL */
}
var * v = &e->v;
v->type = VAR_NULL;
var_let(e, e->ad_var, v, TRUE, FALSE);
}
/* */
@@ -4017,7 +4133,8 @@ void instr_067(env * e)
/* */
void instr_068(env * e)
{
/* CPSH */
/* CPSH obsolete ? si oui a confirmer, remplacer par CPHH => idem CPHA mais avec memo que c'est un element d'une hastable */
/* todo ici ? CPAN <ident> empile la var ad_var en nommant le parametre (et CPHN <ident> idem + maj flag element hashtable) */
if(e->si > e->fin) { e->exception = EX_END; return; }
int lg = lire8(e->si++);
if(e->si + lg - 1 > e->fin) { e->exception = EX_END; return; }
@@ -4033,22 +4150,20 @@ void instr_068(env * e)
strncpy(e->nom, (char *)e->si, lg);
e->si += lg;
/* */
var * v;
var_search(e, &v);
if(e->exception != OK || v == NULL)
e->exception = EX_NOVAR;
var * v = &e->v;
/* A REVOIR avec entry ; v est le pointeur sur la var : empiler */
e->v.type = VAR_PARAM;
if(e->v.type == VAR_PARAM)
{
e->v.ptr = v->ptr; /* si deja un parametre, garder le pointeur */
e->v.etat = v->etat; /* et le flag d'appartenance a une hash */
}
else
{
/* v est le pointeur sur la var : empiler */
/* race cond. : hash' var passed and hash itself, and the sub clear hash : hash'var isn't accessible... */
/* TODO memoriser le pointeur pour gerer ce "race cond." ; le supprimer lors du vidage de _local */
e->v.type = VAR_PARAM;
if(v->type == VAR_PARAM)
e->v.ptr = v->ptr; /* si deja un parametre, garder le pointeur */
else
e->v.ptr = (pointeur)v;
cpush(e, &e->v);
e->v.ptr = (pointeur)v;
e->v.etat = NULL;
}
cpush(e, &e->v);
}
}
/* */
@@ -4093,6 +4208,7 @@ void instr_071(env * e)
{
/* RNXT depuis ad_var, resultat dans var depilee de la call stack (param) */
var * v = &e->v;
e->nom64[0] = 0; e->nom64[1] = 0; e->nom64[2] = 0;
cpop(e, v);
if(e->exception != OK || e->ad_var == NULL)
{
@@ -4189,9 +4305,21 @@ void instr_072(env * e)
}
e->v.type = VAR_PARAM;
if(e->ad_var->type == VAR_PARAM)
{
if(e->ad_var->ptr == NULL)
{
e->exception = EX_VARPARAM_KO;
return;
}
e->v.ptr = e->ad_var->ptr; /* si deja un parametre, garder le pointeur */
e->v.etat = e->ad_var->etat;
}
else
{
e->v.ptr = (pointeur)e->ad_var;
e->v.etat = NULL;
}
e->nom64[0] = 0; e->nom64[1] = 0; e->nom64[2] = 0;
cpush(e, &e->v);
}
/* */
@@ -5880,7 +6008,7 @@ void instr_123(env * e)
return;
}
if(e->ad_var->type == VAR_PARAM)
if((e->ad_var = (var *)e->ad_var->ptr) == NULL) /* travailler avec la var pointee ! */
if((e->ad_var = (var *)e->ad_var->ptr) == NULL) /* travailler avec la var pointee ! mais a priori cas impossible ici */
{
e->exception = EX_VARPARAM_KO;
return;
@@ -5933,7 +6061,7 @@ void instr_124(env * e)
return; /* pas trouve */
}
if(v->type == VAR_PARAM)
if((v = (var *)v->ptr) == NULL) /* travailler avec la var pointee ! */
if((v = (var *)v->ptr) == NULL) /* travailler avec la var pointee ! mais a priori cas impossible ici */
{
e->exception = EX_VARPARAM_KO;
return;
@@ -5972,6 +6100,34 @@ void instr_126(env * e)
nsortedsearchs(e);
}
/* */
void instr_127(env * e)
{
/* CPHH empile dans la call stack la var ad_var sous forme de param + flag appartenance a une hashtable (ad_var_sav est a jour dans ce cas ici ) */
if(e->ad_var == NULL)
{
e->exception = EX_NOADVAR;
return;
}
e->v.type = VAR_PARAM;
if(e->ad_var->type == VAR_PARAM)
{
/* ce cas ne peut pas arriver */
if(e->ad_var->ptr == NULL)
{
e->exception = EX_VARPARAM_KO;
return;
}
e->v.ptr = e->ad_var->ptr; /* si deja un parametre, garder le pointeur */
e->v.etat = e->ad_var->etat;
}
else
{
e->v.ptr = (pointeur)e->ad_var;
e->v.etat = (pointeur)e->ad_var_sav; /* a jour car SADV avant PVAH */
}
e->nom64[0] = 0; e->nom64[1] = 0; e->nom64[2] = 0;
cpush(e, &e->v);
}
/* */
/* */
void instr_250(env * e)
@@ -6032,7 +6188,10 @@ void instr_252(env * e)
e->part = (octet)((ent64)*pe++);
/* selon si appel/retour dans bloc except ou non, pas la meme gestion du retour de l'except */
if(e->except_ex == OK)
{
e->exception = OK; // garder l'erreur de l'appelant quand CALL ok
e->except_ex = ex_ex; // garder l'erreur de l'appelant quand CALL ok
}
else /* CALL en exception ici : à remonter a l'appelant ; ecraser l'ancienne exception, idem decode() */
e->exception = e->except_ex;
/* */
@@ -6056,20 +6215,20 @@ void instr_252(env * e)
hashtable_do(e, HASH_DELETE, &e->g, copy_nom(e, GUV_LOCAL), &v);
}
/* */
ex_ex = e->except_ex; /* sauvegarde */
e->except_ex = OK;
ent64 ex_sav = e->exception; /* sauvegarde */
e->exception = OK;
int bin_indice_prec = e->bin_indice;
SetBinIndex(e);
if(e->except_ex == OK)
if(e->exception == OK)
{
*(pointeur *)(e->ad_var->ptr + ((bin_indice_prec - 1) * 3 + 2) * sizeof(pointeur)) -= 1;
}
else
{
e->exception = e->except_ex; // binaddr inconnu : provoque une sortie immediate (comment gerer l'appelant ?) */
e->exception = e->except_ex; /* binaddr inconnu : provoque une sortie immediate (comment gerer l'appelant ?) creer une exception */
ctx_env_kill = IN_ENDP;
}
e->except_ex = ex_ex; /* restauration */
e->exception = ex_sav; /* restauration */
/* */
e->level--;
}
@@ -6186,7 +6345,10 @@ void instr_254(env * e)
e->part = (octet)((ent64)*pe++);
/* selon si appel/retour dans bloc except ou non, pas la meme gestion du retour de l'except */
if(e->except_ex == OK)
{
e->exception = OK; // garder l'erreur de l'appelant quand DO ok
e->except_ex = ex_ex; // garder l'erreur de l'appelant quand DO ok
}
else
e->exception = e->except_ex; /* DO en exception ici : à remonter a l'appelant ; ecraser l'ancienne exception, idem decode() */
/* */
@@ -6210,18 +6372,19 @@ void instr_254(env * e)
hashtable_do(e, HASH_DELETE, &e->g, copy_nom(e, GUV_LOCAL), &v);
}
/* */
ex_ex = e->except_ex; /* sauvegarde */
ent64 ex_sav = e->exception; /* sauvegarde */
e->exception = OK;
SetBinIndex(e);
if(e->except_ex == OK)
if(e->exception == OK)
{
// pas besoin de decrementer le cpt du nb d'appel a une LIBR
}
else
{
e->exception = e->except_ex; // binaddr inconnu : provoque une sortie immediate (comment gerer l'appelant ?) */
e->exception = e->except_ex; /* binaddr inconnu : provoque une sortie immediate (comment gerer l'appelant ?) creer une exception */
ctx_env_kill = IN_ENDP;
}
e->except_ex = ex_ex; /* restauration */
e->exception = ex_sav; /* restauration */
/* */
e->level--;
}
@@ -6321,7 +6484,7 @@ void (*instr[256])(env * e) = {instr_000,instr_001,instr_002,instr_003,instr_004
instr_090,instr_091,instr_092,instr_093,instr_094,instr_095,instr_096,instr_097,instr_098,instr_099,
instr_100,instr_101,instr_102,instr_103,instr_104,instr_105,instr_106,instr_107,instr_108,instr_109,
instr_110,instr_111,instr_112,instr_113,instr_114,instr_115,instr_116,instr_117,instr_118,instr_119, /* 119 */
instr_120,instr_121,instr_122,instr_123,instr_124,instr_125,instr_126,instr_255,instr_255,instr_255,
instr_120,instr_121,instr_122,instr_123,instr_124,instr_125,instr_126,instr_127,instr_255,instr_255,
instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,
instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,
instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,instr_255,
@@ -6468,6 +6631,7 @@ void (*instr[256])(env * e) = {instr_000,instr_001,instr_002,instr_003,instr_004
; 124 7C PVID lg nom 2+lg enchainement PVAH/PVAI, en dernier supprime dans la hash <ad_var_hash> la var <nom> (avec indirection) (idem DELE mais avec suppression)
; 125 7D SSRC 1 sortedsearch(var) search sorted string in field
; 126 7E SSCS 1 search(var, numField) search sorted string in subfield of the field given
; 127 7F CPHH 1 idem CPHA mais avec flag positionne indiquant l'empilage d'une var appartenant a une hash
;
; 250 FA PROG 1 indique que le binaire est un programme, premiere instruction du binaire sinon endp
; 251 FB LIBR 1 indique que le binaire est une library, non executable directement, premiere instruction du binaire, sinon except (dans les 2 cas)
@@ -6701,10 +6865,23 @@ void NewProcess(env * e, var * prog)
}
else
{
/* dans le fils ici
A essayer */
/* eventuellement a tester :
if (pid == 0) {
setpgid(0, 0);
pause(); // attend que le père donne le terminal
execvp(...);
}
else {
setpgid(pid, pid);
tcsetpgrp(STDIN_FILENO, pid);
kill(pid, SIGCONT); // libère le fils
exit(0);
}
*/
/* dans le fils ici A essayer */
//chdir("/"); // permet de ne pas bloquer un filesystem avec ce process mais attention au path qaudn execvp !
setsid(); // attention aux vars d'env WBIN WLIB WSRC si reset session !
//setsid(); /* bloque le meme terminal/console */
//
// si socket retournee par accept, reste ouverte dans le fils : juste envoyer le descripteur
// Appel de shm_lib : newProcessShmWriter()
@@ -6715,7 +6892,7 @@ void NewProcess(env * e, var * prog)
// TODO gestion console idem windows !!
/* si on arrive ici : execvp n'a pas fonctionne : erreur dans le fils : sortie immediate */
printf("erreur execvp: %d\n", errno);
exit(0);
exit(-1);
}
#else
STARTUPINFO si = { sizeof(si) };
@@ -7287,9 +7464,10 @@ void SetBinIndex(env * ctx)
{
/* chercher dans _binaddr l'indice du source en cours */
hashtable_do(ctx, HASH_READ, &ctx->g, copy_nom(ctx, GUV_BINADDR), &ctx->ad_var);
if(ctx->exception != OK) return;
if(ctx->ad_var == NULL)
{
ctx->except_ex = EX_BINADDRVAR_KO;
ctx->exception = EX_BINADDRVAR_KO;
return;
}
/* recherche indice a partir de e->si */
+3 -2
View File
@@ -134,7 +134,7 @@ typedef struct {
ent64 write; /* buffer */
ent64 misc; /* hashtable/objet et subroutine (si_except) */
ent64s mInternal; /* pour dynamic */
pointeur etat; /* pour module, etat utilise d'appels en appels */
pointeur etat; /* pour module (SUB), etat utilise d'appels en appels ; pour VAR_PARAM indique si variable est un element de hash (PVAH) */
};
} var; /* 40 octets */
@@ -258,7 +258,8 @@ enum {
EX_SQRT_NEG = 42, /* racine carre d'un nombre negatif non calculee */
EX_INT_EXP = 43, /* exponentiation fractionnaire non calculee */
EX_VARPARAM_KO = 44, /* la variable passee en parametre n'est plus presente en memoire */
EXNB = 44 /* MEMO !!!! */
EX_PARAM_NOTFOUND = 45, /* la variable passee en parametre est affectee a un nom de parametre inconnu de la sub */
EXNB = 45 /* MEMO !!!! */
};
typedef struct {
+79
View File
@@ -0,0 +1,79 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024-2026 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#include <stdlib.h>
#include <stdio.h>
#include "langage.h"
#include "dynamic.h"
#include <libssh/libssh.h>
#include <libssh/sftp.h>
/* codes a passer a la fonction setError */
enum {
WSSH_MEM_ERROR = -2,
WSSH_ERROR = -1,
WSSH_OK = 0,
WSSH_SESSION = 1,
WSSH_SESSION_CONNECT = 2,
WSSH_AUTH = 3,
WSSH_CHANNEL = 4,
WSSH_CHANNEL_OPEN = 5,
WSSH_WRITE = 6,
WSSH_READ = 7,
WSSH_EXEC = 8,
WSSH_MODE = 9,
WSSH_SFTP = 10,
WSSH_SFTP_INIT = 11
};
enum {
WSSH_EXEC_MODE = 1,
WSSH_TERMINAL_MODE = 0
};
typedef struct {
ssh_session session;
ssh_channel channel; /* commandes console */
sftp_session sftp;
/* */
int err; /* erreur specifique au module */
int packet; /* taille des paquets lus un par un */
int execMode; /* TRUE si channelExec, FALSE si pseudo terminal */
} modContextSsh;
WAPIDECL void initSsh(env * e, modContextSsh * ctx);
WAPIDECL void freeSsh(env * e, modContextSsh * ctx);
WAPIDECL long setSession(env * e, modContextSsh * ctx, Dynamic * host, Dynamic * user, Dynamic * pwd);
WAPIDECL void freeSession(env * e, modContextSsh * ctx);
WAPIDECL long setChannel(env * e, modContextSsh * ctx, int mode);
WAPIDECL void freeChannel(env * e, modContextSsh * ctx);
WAPIDECL long channelExec(env * e, modContextSsh * ctx, Dynamic * data, Dynamic * resultat, number timeout);
WAPIDECL long channelWrite(env * e, modContextSsh * ctx, Dynamic * data);
WAPIDECL long channelRead(env * e, modContextSsh * ctx, Dynamic * data, number timeout);
/* faire idem channel pour "transfert" (sftp) */
WAPIDECL long setSftp(env * e, modContextSsh * ctx);
WAPIDECL void freeSftp(env * e, modContextSsh * ctx);
+310
View File
@@ -0,0 +1,310 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024-2026 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#include <stdlib.h>
#include <stdio.h>
#include "langage.h"
#include "dynamic.h"
#include "var.h"
#include "ssh.h"
typedef struct {
int error; /* dernier code erreur specifique au module */
//***
modContextSsh ctxSsh;
} modEtat;
enum {
EXMOD_WSSH_SESSION = 1,
EXMOD_WSSH_CHANNEL = 2,
EXMOD_WSSH_SFTP = 3,
EXMOD_WSSH_WRITECHANNEL = 4,
EXMOD_WSSH_EXECCHANNEL = 5,
EXMOD_WSSH_READCHANNEL = 6
};
static int setError(modEtat * p, int err)
{
if(p != NULL)
p->error = err;
return EX_MODERR;
}
#ifdef WINLIB
/* Sous Windows, export de la fonction de base au sein d'une DLL : 1 module = 1 DLL */
__declspec(dllexport) long execModule(env * , var * , var * , var * , void ** );
#endif
long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
{
modEtat * p_etat;
long exc = OK;
// init/end/vers/error sont obligatoires pour tout module
// fonction createServer, arret
// - - - - - - - - - - - - - - - - - - - -
if(etat == NULL)
return EX_MODPARAM;
else
p_etat = (modEtat *)(*etat); /* evite de la faire a chaque fonction */
//
if(param1 != NULL)
if(param1->type == VAR_PARAM)
param1 = (var *)param1->ptr; /* evite de le faire a chaque fonction */
if(param2 != NULL)
if(param2->type == VAR_PARAM)
param2 = (var *)param2->ptr; /* evite de le faire a chaque fonction */
if(param3 != NULL)
if(param3->type == VAR_PARAM)
param3 = (var *)param3->ptr; /* evite de le faire a chaque fonction */
//
/* ----------------------------------------------------------------------------------------------- */
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
if(modFnIs(e, "init", 4))
{
// alloc ptr sur zone memoire pour memoriser l'etat du module
*etat = memalloc(e, sizeof(modEtat));
if(*etat == NULL)
exc = EX_MODETAT;
else
{
p_etat = (modEtat *)(*etat);
p_etat->error = 0;
//***
initSsh(e, &p_etat->ctxSsh);
}
}
else if(modFnIs(e, "end", 3))
{
// liberation specifique au module avant arret process
p_etat = (modEtat *)(*etat);
if(p_etat != NULL)
{
freeSsh(e, &p_etat->ctxSsh);
//***
memfree(e, p_etat);
}
}
else if(modFnIs(e, "vers", 4))
{
// renvoie la version du module/plugins
if(param1 == NULL)
exc = EX_MODPARAM;
else
{
if(param1->type == VAR_DYNAMIC)
dynLet(e, param1, "1", 1); //*** version en alpha
else if(param1->type == VAR_NUMBER)
param1->num = NUM_UN; //*** version en numerique
else
exc = EX_MODPARAM; // variable en parametre du mauvais type
}
}
else if(modFnIs(e, "error", 5))
{
// renvoie la derniere erreur specifique au module
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1 == NULL)
exc = EX_MODPARAM;
else
{
if(param1->type == VAR_NUMBER)
{
param1->num = (ent64)(NUM_FACTEUR * p_etat->error);
/* extend error */
if(param2 != NULL)
if(param2->type == VAR_NUMBER)
param2->num = (ent64)(NUM_FACTEUR * p_etat->ctxSsh.err);
}
else
exc = EX_MODPARAM; // variable en parametre du mauvais type
}
}
/* ============================================================================================= */
else if(modFnIs(e, "openSession", 11))
{
/* ouvre la connexion ssh au serveur */
if(p_etat == NULL)
return (exc = EX_MODETAT);
else if(param1 == NULL || param2 == NULL || param3 == NULL)
exc = EX_MODPARAM;
else if(param1->type != VAR_DYNAMIC || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
exc = EX_MODPARAM;
else
{
// param1 = host, param2 = user, param3 = password
if(setSession(e, &p_etat->ctxSsh, param1, param2, param3) != WSSH_OK)
exc = setError(p_etat, EXMOD_WSSH_SESSION);
else
exc = OK;
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "endSession", 10))
{
/* ferme la connexion ssh au serveur */
if(p_etat == NULL)
return (exc = EX_MODETAT);
else
{
freeSession(e, &p_etat->ctxSsh);
exc = OK;
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "execChannel", 11))
{
/* envoi d'une commande "one shot" (param1), pas besoin du 'openChannel' ici, lecture du resultat avec 'readChannel' et renvoi du resultat dans param2, timeout en sec. dans param3 */
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1 == NULL || param2 == NULL || param3 == NULL)
exc = EX_MODPARAM;
else if(param1->type != VAR_DYNAMIC || param2->type != VAR_DYNAMIC)
exc = EX_MODPARAM;
else
{
number timeout;
if(var_conv_num(e, param3, &timeout))
{
if(channelExec(e, &p_etat->ctxSsh, param1, param2, timeout) != WSSH_OK)
exc = setError(p_etat, EXMOD_WSSH_EXECCHANNEL);
else
exc = OK;
}
else
exc = EX_MODPARAM;
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "openChannel", 11))
{
/* ouvre un canal de type "terminal" avec le serveur
faire un 'readChannel' la premiere fois apres le 'openChannel', puis enchainer les ecritures (commandes) et lectures (resultat)
*/
if(p_etat == NULL)
return (exc = EX_MODETAT);
else
{
if(setChannel(e, &p_etat->ctxSsh, WSSH_TERMINAL_MODE) != WSSH_OK)
exc = setError(p_etat, EXMOD_WSSH_CHANNEL);
else
exc = OK;
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "writeChannel", 12))
{
/* envoi d'une commande au pseudo-terminal */
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1 == NULL)
exc = EX_MODPARAM;
else if(param1->type != VAR_DYNAMIC)
exc = EX_MODPARAM;
else
{
if(channelWrite(e, &p_etat->ctxSsh, param1) != WSSH_OK)
{
exc = setError(p_etat, EXMOD_WSSH_WRITECHANNEL);
}
else
exc = OK;
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "readChannel", 11))
{
/* lecture du resultat d'une commande (stdout dans param1) en mode terminal, timeout en sec. dans param2 */
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1 == NULL || param2 == NULL)
exc = EX_MODPARAM;
else if(param1->type != VAR_DYNAMIC)
exc = EX_MODPARAM;
else
{
number timeout;
if(var_conv_num(e, param2, &timeout))
{
if(channelRead(e, &p_etat->ctxSsh, param1, timeout) != WSSH_OK)
{
exc = setError(p_etat, EXMOD_WSSH_READCHANNEL);
}
else
exc = OK;
}
else
exc = EX_MODPARAM;
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "closeChannel", 12))
{
/* ferme le channel mais laisse la connexion au serveur ouverte (mode terminal seulement, inutile en mode exec) */
if(p_etat == NULL)
exc = EX_MODETAT;
else
{
freeChannel(e, &p_etat->ctxSsh);
exc = OK;
}
}
/* ============================================================================================= */
else if(modFnIs(e, "openSftp", 8))
{
/* ouvre un canal de type "transfert" avec le serveur */
if(p_etat == NULL)
return (exc = EX_MODETAT);
else
{
if(setSftp(e, &p_etat->ctxSsh) != WSSH_OK)
exc = setError(p_etat, EXMOD_WSSH_SFTP);
else
exc = OK;
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "closeSftp", 9))
{
/* ferme le canal "transfert" mais laisse la connexion au serveur ouverte */
if(p_etat == NULL)
exc = EX_MODETAT;
else
{
freeSftp(e, &p_etat->ctxSsh);
exc = OK;
}
}
/* ----------------------------------------------------------------------------------------------- */
else
{
if(p_etat == NULL)
exc = EX_MODETAT;
else
exc = setError(p_etat, EX_MODFUNC); // fonction non prise en charge
}
//
return exc;
}
+292
View File
@@ -0,0 +1,292 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024-2026 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#include "ssh.h"
#ifdef WINLIB
#include <WinSock2.h>
#else
#include "poll.h"
#endif
// force exporting
#ifdef WINLIB
#undef WAPIDECL
#define WAPIDECL __declspec(dllexport)
#else
#undef WAPIDECL
#define WAPIDECL
#endif
/* ---------------------------------------------------- */
/*
unix : -lssh -lcrypto -lssl -lz (dependances openssl zlib, verification avec : ldd /usr/lib/libssh.so)
sudo apt update
sudo apt install -y \
openssl libssl-dev \
zlib1g zlib1g-dev \
libssh-dev
openssl → binaire en ligne de commande
libssl-dev → headers + librairies pour compiler en C
zlib1g → runtime
zlib1g-dev → headers (zlib.h) + .so
libssh-dev → headers et libs de développement
windows : libssh.lib (et libssh compile avec msvc sinon ko)
ajouter => libssl.lib libcrypto.lib zlib.lib ws2_32.lib (car dependances openssl, zlib, socket)
git clone https://github.com/microsoft/vcpkg
cd vcpkg
bootstrap-vcpkg.bat
vcpkg install libssh:x64-windows
vcpkg install zlib:x64-windows
vcpkg install openssl:x64-windows
+ compil/link => cl main.c /I"path\to\vcpkg\installed\x64-windows\include" /link /LIBPATH:"path\to\vcpkg\installed\x64-windows\lib" libssh.lib libssl.lib libcrypto.lib zlib.lib ws2_32.lib
=> repertoire ou se trouve vcpkg (install depuis git) :
C:\Users\Poupougne42\source\vcpkg-master\installed\x64-windows
À l'exécution il faut :
libssl-*.dll
libcrypto-*.dll
dans :
même dossier que .exe ou dans le PATH
=== CERTIFICAT auto signé
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes
avec windows, c'est pareil, sauf initsocket WAStartup, type SOCKET et pas int, closesocket() et il faut fournir un fichier ca (https://curl.se/ca/cacert.pem) pour la verification des certificats
https://kb.firedaemon.com/...openssl-binary-distributions : binaires openssl sous windows (3.5.6 LTS ok), ok avec libssh 0.12.x (eventuellement 0.11.x)
*/
/* ****** PRIVATE ************************ */
int ssh_read_timeout(env * e, modContextSsh * ctx, Dynamic * data, number timeout)
{
#ifndef WINLIB
struct pollfd fd;
fd.fd = ssh_get_fd(ctx->session),
fd.events = POLLIN;
/* lecture avec timeout */
int cr = poll(&fd, 1, timeout * 1000 / NUM_FACTEUR);
#else
WSAPOLLFD fd;
fd.fd = (SOCKET)ssh_get_fd(ctx->session);
fd.events = POLLRDNORM;
fd.revents = 0;
/* lecture avec timeout */
int cr = WSAPoll(&fd, 1, timeout * 1000 / NUM_FACTEUR);
#endif
if (cr == 0)
return SSH_AGAIN; /* pas de donnees ou timeout */
if (cr < 0)
return SSH_ERROR;
/* lecture des donnees presentes */
return ssh_channel_read(ctx->channel, data->mPtr + data->mLg, ctx->packet, 0); /* 0 signifie lire stdout, 1 pour stderr */
}
/* ****** PUBLIC ************************ */
WAPIDECL void initSsh(env * e, modContextSsh * ctx)
{
ctx->packet = 16000;
ctx->execMode = WSSH_EXEC_MODE; /* for channel management */
ctx->channel = NULL;
ctx->session = NULL;
}
WAPIDECL void freeSsh(env * e, modContextSsh * ctx)
{
freeSession(e, ctx);
}
WAPIDECL long setSession(env * e, modContextSsh * ctx, Dynamic * host, Dynamic * user, Dynamic * pwd)
{
freeSession(e, ctx);
/* */
if((ctx->session = ssh_new()) == NULL)
return (ctx->err = WSSH_SESSION);
/* */
ssh_options_set(ctx->session, SSH_OPTIONS_HOST, host->mPtr);
ssh_options_set(ctx->session, SSH_OPTIONS_USER, user->mPtr);
/* */
if(ssh_connect(ctx->session) != SSH_OK)
{
ssh_free(ctx->session);
ctx->session = NULL;
return (ctx->err = WSSH_SESSION_CONNECT);
}
/* */
if(ssh_userauth_password(ctx->session, NULL, pwd->mPtr) != SSH_AUTH_SUCCESS)
{
//ssh_channel_free(ctx->channel);
freeSession(e, ctx);
return (ctx->err = WSSH_AUTH);
}
return (ctx->err = WSSH_OK);
}
WAPIDECL void freeSession(env * e, modContextSsh * ctx)
{
freeChannel(e, ctx);
freeSftp(e, ctx);
if(ctx->session)
{
ssh_disconnect(ctx->session);
ssh_free(ctx->session);
ctx->session = NULL;
}
}
WAPIDECL long setChannel(env * e, modContextSsh * ctx, int mode)
{
freeChannel(e, ctx);
ctx->execMode = mode;
ssh_set_blocking(ctx->session, TRUE); /* bloquant */
/* */
if((ctx->channel = ssh_channel_new(ctx->session)) == NULL)
return (ctx->err = WSSH_CHANNEL);
/* */
if(ssh_channel_open_session(ctx->channel) != SSH_OK)
{
ssh_channel_free(ctx->channel);
ctx->channel = NULL;
return (ctx->err = WSSH_CHANNEL_OPEN);
}
if(ctx->execMode == WSSH_EXEC_MODE)
return (ctx->err = WSSH_OK);
/* */
/* Allocation d'un pseudo-terminal + shell interactif (channel reste ouvert dans ce cas) */
if(ssh_channel_request_pty(ctx->channel) != SSH_OK)
{
ssh_channel_free(ctx->channel);
ctx->channel = NULL;
return (ctx->err = WSSH_CHANNEL_OPEN);
}
if(ssh_channel_request_shell(ctx->channel) != SSH_OK)
{
ssh_channel_free(ctx->channel);
ctx->channel = NULL;
return (ctx->err = WSSH_CHANNEL_OPEN);
}
return (ctx->err = WSSH_OK);
}
WAPIDECL void freeChannel(env * e, modContextSsh * ctx)
{
if(ctx->channel)
{
if(ctx->execMode == WSSH_TERMINAL_MODE)
{
ssh_channel_write(ctx->channel, "exit\n", 5);
ssh_channel_send_eof(ctx->channel);
}
ssh_channel_close(ctx->channel);
ssh_channel_free(ctx->channel);
ctx->channel = NULL;
}
}
WAPIDECL long channelExec(env * e, modContextSsh * ctx, Dynamic * data, Dynamic * resultat, number timeout)
{
long cr;
cr = setChannel(e, ctx, WSSH_EXEC_MODE);
if(cr != WSSH_OK)
return (ctx->err = cr);
/* send command to channel, one shot (ssh_channel_request_exec ferme le channel a chaque commande) */
if(ssh_channel_request_exec(ctx->channel, data->mPtr) != SSH_OK)
cr = (ctx->err = WSSH_EXEC);
else
cr = channelRead(e, ctx, resultat, timeout); /* lecture du resultat en mode bloquant suite a l'envoi de la requete */
/* */
return cr;
}
WAPIDECL long channelWrite(env * e, modContextSsh * ctx, Dynamic * data)
{
if(ctx->execMode != WSSH_TERMINAL_MODE)
return (ctx->err = WSSH_MODE);
/* send command to channel */
if(ssh_channel_write(ctx->channel, data->mPtr, data->mLg) < 0)
return (ctx->err = WSSH_WRITE);
else
return (ctx->err = WSSH_OK);
/* le channel reste ouvert */
}
WAPIDECL long channelRead(env * e, modContextSsh * ctx, Dynamic * data, number timeout)
{
ssh_set_blocking(ctx->session, FALSE); /* non bloquant */
/* read response from serveur */
dynSetLen(e, data, 0);
/* Lire la sortie, mode non bloquant ici (explicite avec read_nonblocking) */
for(;;)
{
if(dynCtrl(e, data, data->mLg + ctx->packet, TRUE))
{
return (ctx->err = WSSH_MEM_ERROR); /* erreur memoire */
}
int nb = ssh_read_timeout(e, ctx, data, timeout);
/* */
if(nb == SSH_ERROR)
return (ctx->err = WSSH_READ);
if(nb == SSH_AGAIN || nb == 0)
return (ctx->err = WSSH_OK); /* rien a lire pour l'instant ou sortie en timeout ou fin des donnees */
/* */
if(nb > 0)
dynSetLen(e, data, data->mLg + nb);
/* continue reading */
}
}
WAPIDECL long setSftp(env * e, modContextSsh * ctx)
{
if((ctx->sftp = sftp_new(ctx->session)) == NULL)
return (ctx->err = WSSH_SFTP);
/* */
if(sftp_init(ctx->sftp) != SSH_OK)
{
freeSftp(e, ctx);
return (ctx->err = WSSH_SFTP_INIT);
}
return (ctx->err = WSSH_OK);
}
/*
sftp_file file = sftp_open(sftp, "/etc/hostname", O_RDONLY, 0); // NULL : erreur open
nbytes = sftp_read(file, buffer, sizeof(buffer)); // tant que nbytes > 0
sftp_close(file);
*/
WAPIDECL void freeSftp(env * e, modContextSsh * ctx)
{
if(ctx->sftp)
{
sftp_free(ctx->sftp);
ctx->sftp = NULL;
}
}