Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6bea78591 | ||
|
|
0445f10ebe | ||
|
|
ad317a2070 | ||
|
|
e0eaf6f9e8 | ||
|
|
b70cee802b |
No files matched your search
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, ¶m1); // seule exception possible ici : EX_BUFOVF car pas/plus de parametre empile
|
||||
if(!e->exception) p1 = ¶m1;
|
||||
cpop(e, ¶m2);
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user