Author SHA1 Message Date
fred 0d32522c75 WIP 2026-10-31 20:37:56 +01:00
22 changed files with 987 additions and 484 deletions

No files matched your search

+7 -4
View File
@@ -1,8 +1,9 @@
#define ARG_DEBUG "d"
#define ARG_TRACE "t"
#define ARG_DISASM "u"
#define ARG_COMPRESS "c"
#define ARG_DEBUG "d" /* avec lw */
#define ARG_TRACE "t" /* avec lw */
#define ARG_DISASM "u" /* avec lwa */
#define ARG_COMPRESS "c" /* avec lwa */
#define ARG_SOURCE "s" /* avec lwc */
void GetArgs(env * e, int argc, char * argv[], Dynamic * arg)
{
@@ -21,6 +22,8 @@ void GetArgs(env * e, int argc, char * argv[], Dynamic * arg)
dynStoreSz(e, arg, 1, ++nbOpt, ARG_DISASM, 1, cFM, cVM);
else if(strcmp(argv[a], "-" ARG_COMPRESS) == 0)
dynStoreSz(e, arg, 1, ++nbOpt, ARG_COMPRESS, 1, cFM, cVM);
else if(strcmp(argv[a], "-" ARG_SOURCE) == 0)
dynStoreSz(e, arg, 1, ++nbOpt, ARG_SOURCE, 1, cFM, cVM);
//
else if(strncmp(argv[a], "-WBIN:", 6) == 0 && strlen(argv[a]) > 6)
dynStoreSz(e, arg, 3, DYN_NONE, &argv[a][6], DYN_LGNONE, cFM, DYN_NONE); // memo (.o .so)
+4 -2
View File
@@ -671,7 +671,9 @@ int assembler(env * e, char * fichier, int * cptLig, int compress)
PCODE(tmp.mPtr[p]);
break;
case IN_INCL:
// INCL (lg=0 possible si rien)
// INCL (lg=0 possible si rien) - ne pas mettre dans le pcode car ne sert plus
i++;
break;
dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
if(tmp.mLg < 0 || tmp.mLg > 255) { ret = -4; break; } // erreur longueur nom variable
num = tmp.mLg;
@@ -945,7 +947,7 @@ int disassembler(env * e, char * fichier)
case IN_PVHD:
case IN_PVID:
case IN_PNAM:
case IN_INCL:
//case IN_INCL:
// CPAN / CPHN / PARM / PVAR / PVAH / PVAI / DELE / NLET / PNAM / INCL / PHDE / PIDE
si++;
lg = pcode.ptr[si++];
+2 -1
View File
@@ -66,7 +66,8 @@ char * strerr[] = {
"EX_INT_EXP Fractional exponentiation is not calculated",
"EX_VARPARAM_KO Null parameter pointer",
"EX_PARAM_NOTFOUND Named parameter not found", // 45
"EX_NUMOVF Numeric overflow"
"EX_NUMOVF Numeric overflow",
"EX_INPUT_TTY Cannot read from terminal or stdin"
};
enum {
+101 -10
View File
@@ -28,6 +28,7 @@
#include "langage.h"
#include "dynamic.h"
#include "lex.h"
#include "instr.h"
env e;
@@ -181,17 +182,103 @@ enum {
static void formatage_asm(Dynamic * s, Dynamic * f)
{
// TODO
Dynamic trav, lig; /* variables de travail */
dynInit(&e, &trav, 0);
dynInit(&e, &lig, 0);
long sdlw = 0;
if(dynIndexSz(&e, s, "\r\n", 2, 1) > -1)
{
/* saut de ligne windows : supprimer \r et les remettre a la fin */
sdlw = 1;
/* supprimer les \r de la chaine ! */
dynErase(&e, s, "\r");
}
//
long numlig = 0, niveau = 0, flag_trt;
dynRemove(&e, s, NULL, 0, DYN_TRUE);
while(dynRemove(&e, s, &lig, 10, DYN_FALSE) > -1)
{
// traiter chaque ligne
numlig++;
if(lig.mLg == 0)
continue; // ligne vide
//
// mettre dans trav la ligne sans le debut (blanc/tab)
int i, pos = -1;
for(i = 0; i < lig.mLg; i++)
{
if(lig.mPtr[i] == 32 || lig.mPtr[i] == 9)
continue;
pos = i;
break;
}
if(pos == -1)
continue; /* ligne avec que des blancs/tabs : idem vide */
/* */
dynSubstr(&e, &lig, &trav, pos, lig.mLg - pos, DYN_NONE, DYN_NONE, DYN_NONE, DYN_NONE);
/* recherche instr dans la liste */
int instr = -1, trouve = 0;
if(lig.mPtr[pos] == ';')
trouve = 1;
for(i = 0; i < 256 && !trouve; i++)
{
if(strncmp(libInstr + i * 4, trav.mPtr, 4) == 0)
{
// instruction <instr> trouvee
trouve = 1;
instr = i;
}
}
if(!trouve)
flag_trt = 0; // aligner sur le bloc courant, idem instruction ou commentaire
else if(instr == IN_PROG || instr == IN_LIBR || instr == IN_BACK || instr == IN_SUBR || instr == IN_PHDS || instr == IN_PIDS)
flag_trt = 1;
else if(instr == IN_ENDP || instr == IN_ENDS || instr == IN_ENDL)
flag_trt = 2;
else if(instr == IN_EXCE)
flag_trt = 3;
else
flag_trt = 0;
//
if(flag_trt == 1)
{
// niveau +1 apres
dynFmt(&e, &trav, &lig, 'R', ' ', lig.mLg + (niveau++) * TAB_COUNT);
}
else if(flag_trt == 2)
{
// niveau -1 avant
if(niveau > 0)
niveau--;
dynFmt(&e, &trav, &lig, 'R', ' ', lig.mLg + niveau * TAB_COUNT);
}
else if(flag_trt == 3)
{
// niveau -1 local sans changement
if(niveau > 0)
dynFmt(&e, &trav, &lig, 'R', ' ', lig.mLg + (niveau-1) * TAB_COUNT);
else
dynFmt(&e, &trav, &lig,'R', ' ', lig.mLg + niveau * TAB_COUNT);
}
else
{
// 0 : niveau courant
dynFmt(&e, &trav, &lig, 'R', ' ', lig.mLg + niveau * TAB_COUNT);
}
// changer la ligne courante avec sa version formatee
dynStoreSz(&e, f, numlig, DYN_NONE, lig.mPtr, lig.mLg, 10, DYN_NONE);
}
//
if(sdlw)
dynChange(&e, f, "\n", "\r\n", 0); /* remettre les sauts de ligne windows (0 = tous) */
//
dynFree(&e, &trav);
dynFree(&e, &lig);
}
static void formatage(Dynamic * s, Dynamic * f, int type)
static void formatage(Dynamic * s, Dynamic * f)
{
// s : source ; f : source apres formatage, type : 1 w, 2 pcode
if(type == 2)
{
formatage_asm(s, f);
return;
}
// s : source ; f : source apres formatage
//Dynamic token; /* contient les tokens suite au decodage lex d'une ligne */
ent16 tok; //,tok2,tok3; /* token lu par la macro ci-dessous "nreg" */
long n; /* indice en cours dans les token (parametre de la macro "nreg") base 1 */
@@ -411,7 +498,7 @@ int main(int argc, char * argv[])
if(strcmp(argv[1], "-w") == 0)
type = 1;
else if(strcmp(argv[1], "-wa") == 0)
type = 2; // formatage du pcode (fichier .wa) TODO
type = 2; // formatage du pcode (fichier .wa)
else
{
printf("Usage: lwf [-w|-wa] <source>\n");
@@ -429,7 +516,11 @@ int main(int argc, char * argv[])
}
else
{
formatage(&source, &formate, type);
if(type == 2)
formatage_asm(&source, &formate);
else
formatage(&source, &formate);
/* */
printf("%s\n", formate.mPtr);
if(dynWrite(&e, &formate, argv[argfic]) != OK)
{
+100 -1
View File
@@ -341,6 +341,21 @@ long tok2number(env * e, ent64s * numb, Dynamic * valex, Dynamic * tmp, Dynamic
}
}
long tok2negnumber(env * e, ent64s * numb, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
{
dynField(e, valex, tmp, 1, norig(n), cFM, cVM, 1);
hex2str(e, tmp, encours);
*numb = - dynToNumber(e, encours); // negatif ici
if(encours->mInternal != DYN_OK)
return TERM_ERR; /* TODO erreur de conversion numerique */
else
{
/* reconvertir en chaine dans <encours>, au bon format */
dynLet(e, encours, Int64ToSz(e, *numb, TRUE, 0), DYN_LGNONE);
return TERM_NUM;
}
}
long tok2string(env * e, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
{
dynField(e, valex, tmp, 1, norig(n), cFM, cVM, 1);
@@ -521,6 +536,16 @@ long terme(env * e, ent16 t, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
tok = nreg(n);
return ret; /* encours contient le number */
}
/* ne marche pas sur des expressions du type : let x = x - 1 */
//if(t == r.minus && (nreg(n+1) == r.numberint || nreg(n+1) == r.numberdec))
//{
// n++;
// ent64s numb;
// ret = tok2negnumber(e, &numb, valex, tmp, encours); /* token "n" */
// n++;
// tok = nreg(n);
// return ret; /* encours contient le number */
//}
if(t == r.stringq || t == r.stringdq)
{
ret = tok2string(e, valex, tmp, encours); /* token "n" */
@@ -1245,6 +1270,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
printf("Erreur ligne %dc%s : code trouve apres la fin du programme\n", numlig, tmp->mPtr);
return DYN_ERR; /* TODO numeroter les erreurs */
}
if(trav.mLg > 0)
dynConcat(e, resultat, &trav); /* edition ligne de source dans le code assembleur wa (mis en commentaire) */
/* -------------------------------------------------------------------------------------- */
if(numNiv == 0)
{
@@ -1652,7 +1679,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
/* -------------------------------------------------------------------------------------- */
if(tok == r.foreach)
{
// TODO foreach num in 1,10,1 debut/fin/incr
// foreach num in 1,10,1 debut/fin/incr / foreach var in dynamic / foreach var in hashtable
n++;
dynSetLen(e, &trav, 0);
dynSetLen(e, &envers, 0);
@@ -2970,6 +2997,60 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
return DYN_ERR;
}
void source_include_tree(env * e, Dynamic * meta, Dynamic * resultat, Dynamic * tmp)
{
/*
(global) (local) (filename)
; 1 >1 fichier: 1
; 20 | >19 include: 2
; 30 | | >10 include2: 3
; 40 | | <11 2
; 42 | <20 1
; 44 | >21 include3: 2
; 50 | <23 1
; 60
*/
dynConcatSz(e, resultat, "; ----------------------------------------------\n", DYN_LGNONE);
long precLevel = 0;
long cpt, nb = dynDcount(e, meta, cVM, META_GLOBAL_LN, cFM);
for(cpt = 1; cpt <= nb; cpt++)
{
long numGlobal = dynFieldAsNumber(e, meta, META_GLOBAL_LN, cpt, cFM, cVM);
long numLocal = dynFieldAsNumber(e, meta, META_LOCAL_LN, cpt, cFM, cVM);
long level = dynFieldAsNumber(e, meta, META_LEVEL, cpt, cFM, cVM);
/* */
dynFmtNumber(e, numGlobal, tmp, 'R', ' ', 8);
dynConcatSz(e, resultat, "; ", 2);
dynConcat(e, resultat, tmp);
dynConcatSz(e, resultat, " ", 2);
/* */
dynField(e, meta, tmp, META_FILENAME, cpt, cFM, cVM, 1);
/* */
for(long i = 1; i < level; i++)
dynConcatSz(e, resultat, "| ", 7);
if(precLevel < level)
{
dynConcatSz(e, resultat, ">", 1);
dynConcatSz(e, resultat, Int64ToSz(e, numLocal, FALSE, 0), DYN_LGNONE);
dynConcatSz(e, resultat, " ", 1);
dynConcat(e, resultat, tmp);
dynConcatSz(e, resultat, ":\n", 2);
}
else
{
dynConcatSz(e, resultat, "<", 1);
dynConcatSz(e, resultat, Int64ToSz(e, numLocal, FALSE, 0), DYN_LGNONE);
dynConcatSz(e, resultat, "\n", 1);
}
/* */
precLevel = level;
}
/* FmtNumber(e, numlig, tmp, 'R', ' ', 8); // nb total de lignes, tous fichiers include confondus
dynConcatSz(e, resultat, "; ", 2);
dynConcat(e, resultat, tmp); */
dynConcatSz(e, resultat, "; ----------------------------------------------\n", DYN_LGNONE);
}
/* ***************************************************************************************************** */
int main(int argc, char * argv[])
@@ -3012,6 +3093,7 @@ int main(int argc, char * argv[])
dynExtractField(&e, &arg, 4, &wsrc);
dynExtractField(&e, &arg, 5, &wlib);
dynExtractSubField(&e, &arg, 2, 1, &file); // file = fichier.w a compiler
int arg_source = dynLocateSz(&e, &arg, ARG_SOURCE, cVM, 1, cFM); /* TRUE si option pour ajouter le source w dans le code assembleur genere */
/* */
for(;;)
{
@@ -3058,6 +3140,8 @@ int main(int argc, char * argv[])
if(wsrc.mPtr[wsrc.mLg - 1] != e.path_sep[0])
dynConcatSz(&e, &wsrc, e.path_sep, 1); // ajoute le / si absent a la fin
dynStore(&e, &srcdbg, META_WSRC, DYN_NONE, &wsrc, cFM, DYN_NONE);
if(arg_source)
source_include_tree(&e, &srcdbg, &resultat, &tmp);
//
if(lire_regles_lex(&e, &regles, "wlex") != DYN_OK)
{
@@ -3078,6 +3162,21 @@ int main(int argc, char * argv[])
{
lex(&e, &regles, &ligne, &valex);
/* */
dynSetLen(&e, &trav, 0);
if(arg_source)
{
long localnumlig;
GetFile(&e, numlig + 1, &srcdbg, 1, &tmp, &localnumlig);
/* ; <file>:<numlig_local> | <source> */
dynConcatSz(&e, &trav, "; ", 2);
dynConcat(&e, &trav, &tmp);
dynConcatSz(&e, &trav, ":", 1);
dynConcatSz(&e, &trav, Int64ToSz(&e, localnumlig, FALSE, 8), DYN_LGNONE);
dynConcatSz(&e, &trav, " | ", 3);
dynConcat(&e, &trav, &ligne);
dynConcatSz(&e, &trav, "\n", 1);
}
/* */
ret = parse(&e, &valex, &resultat, &tmp, &encours, &file);
/* */
if(ret == 0)
+11
View File
@@ -84,6 +84,17 @@ WAPIDECL char * raz_nom(env * e)
return e->nom;
}
WAPIDECL int nom_is(env * e, const char * s)
{
long lg = strlen(s);
if(lg < 1 || lg > 24)
return FALSE;
ent64 f[3];
f[0] = 0; f[1] = 0; f[2] = 0;
strncpy((char *)f, s, lg);
return (e->nom64[0] == f[0] && e->nom64[1] == f[1] && e->nom64[2] == f[2]);
}
WAPIDECL int modFnIs(env * e, const char * fn, int lg)
{
// modifier l'endroit ou e->fn est mis a jour : verif fn64[0 1 2] est bien remis a zero avant la maj
+1
View File
@@ -29,6 +29,7 @@ WAPIDECL void init_env(env * e);
WAPIDECL char * copy_nom(env * e, const char * s);
WAPIDECL char * raz_nom(env * e);
WAPIDECL int nom_is(env * e, const char * s);
WAPIDECL int modFnIs(env * e, const char * fn, int lg);
/* ************************************************************************** */
+84
View File
@@ -234,6 +234,19 @@ WAPIDECL void hashtable_do(env * e, int action, var * varht, char * nom, var **
}
}
WAPIDECL void hashtable_deleteentry(env * e, var * varht, var * content)
{
/* cf. hashtable_do / DELETE */
/* liberer la variable "pentry->content" ; si PARAM, libere la var pointee */
var_free(e, content, TRUE);
entry * pentry = (entry *)((pointeur)content - 3 * sizeof(ent64));
pentry->nom1 = 0;
pentry->nom2 = 0;
pentry->nom3 = 0;
pentry->content.type = 0;
((entry *)varht->ptr)->content.ptr = NULL; /* securite si dans select/next */
}
WAPIDECL var * hashtable_writeinfirstfreeentry(env * e, var * varht, char * nom, var * v)
{
if(varht == NULL || v == NULL || nom == NULL)
@@ -515,4 +528,75 @@ WAPIDECL void hashtable_printdebug(env * e, var * varht, int detail)
printf("taille totale=%lld, occupee=%lld (taux %lld%%), nb item=%lld\n", tot, occ, occ * 100 / tot, nb);
}
WAPIDECL void hashtable_analyze(env * e, var * varht)
{
entry * pentry; /* pointe sur une entree */
entry * pchain; /* pointe sur la premiere du groupe, servant au chainage */
entry * pchain_first; /* premier bloc */
ent64 groupe; /* groupe en cours */
/* affiche le contenu d'une hashtable */
if(varht == NULL)
return;
if(varht->type == VAR_PARAM)
varht = (var *)varht->ptr; /* travailler avec la var pointee ! */
if(varht == NULL)
return;
if(varht->type != VAR_HASHTABLE && varht->type != VAR_OBJECT)
return;
if(e->demon)
{
dynPrintfInt64(e, "hashtable analyze modulo=" PRINTF_MARK " separateur=", varht->modulo, 0);
dynPrintfInt64(e, PRINTF_MARK "\n", varht->separateur, 0);
}
else
printf("hashtable analyze modulo=%lld separateur=%lld\n", varht->modulo, varht->separateur);
/* */
ent64 nb_entry, occ_entry, nb_item_group, nb_group_1entry = 0, nb_empty_group = 0, nb_item = 0;
ent64 occ_entry_min = varht->separateur/sizeof(entry), occ_entry_max = 0;
ent64 nb_entry_min = (ent64)(-1), nb_entry_max = 0;
ent64 nb_item_group_min = (ent64)(-1), nb_item_group_max = 0;
/* */
pchain = (entry *)varht->ptr;
for(groupe = 0; groupe < varht->modulo; groupe++)
{
nb_entry = 0;
nb_item_group = 0;
pchain_first = pchain;
do
{
nb_entry++;
occ_entry = 0;
pentry = pchain + 1; /* la premiere est toujours "occupee", utilisee en interne par la hashtable : ne pas mettre dans les stats */
while((ent64)pentry - (ent64)pchain < varht->separateur)
{
if((pentry->nom1 | pentry->nom2 | pentry->nom3 | pentry->content.type) == 0)
; /* entree libre */
else
{
occ_entry++; /* entree occupee */
nb_item_group++;
nb_item++;
}
pentry++;
}
/* */
if(occ_entry < occ_entry_min) occ_entry_min = occ_entry;
if(occ_entry > occ_entry_max) occ_entry_max = occ_entry;
/* chainage */
} while ((pchain = (entry *)pchain->chainage_avant) != 0);
pchain = (entry *)((ent64)pchain_first + varht->separateur);
/* */
if(nb_entry < nb_entry_min) nb_entry_min = nb_entry;
if(nb_entry > nb_entry_max) nb_entry_max = nb_entry;
if(nb_item_group < nb_item_group_min) nb_item_group_min = nb_item_group;
if(nb_item_group > nb_item_group_max) nb_item_group_max = nb_item_group;
if(nb_item_group == 0) nb_empty_group++;
if(nb_entry == 1) nb_group_1entry++;
}
printf(" => nb bloc/group: min=%lld, max=%lld, 1bloc=%lld/%lld\n", nb_entry_min, nb_entry_max, nb_group_1entry, varht->modulo);
printf(" => occ bloc: min=%lld, max=%lld (/%lld)\n", occ_entry_min, occ_entry_max, varht->separateur/sizeof(entry) - 1);
printf(" => nb item/group: min=%lld, max=%lld, empty=%lld/%lld\n", nb_item_group_min, nb_item_group_max, nb_empty_group, varht->modulo);
printf(" => nb item total=%lld\n", nb_item);
}
/* ********************************************** */
+2
View File
@@ -33,10 +33,12 @@ WAPIDECL void hashtable_clear(env *e, var * varht);
WAPIDECL long hashtable_count(env *e, var * varht);
WAPIDECL var * hashtable_lastitemwritten(var * varht);
WAPIDECL var * hashtable_writeinfirstfreeentry(env * e, var * varht, char * nom, var * v);
WAPIDECL void hashtable_deleteentry(env * e, var * varht, var * content);
WAPIDECL void hashtable_serialize(env * e, var * varht, var * out);
WAPIDECL void hashtable_printdebug(env * e, var * varht, int detail);
WAPIDECL void hashtable_analyze(env * e, var * varht);
/* ********************************************** */
#endif
+173 -274
View File
@@ -87,8 +87,8 @@ void dyn_printdebug(env * e, var * v, int detail)
#include "lzw.h"
/* seules variables globales : celle indiquant un signal de terminaison du programme et celles pour basculer en mode debug on/off ! */
octet ctx_env_kill = 0; /* mis a 255 si signal de terminaison */
octet ctx_env_debug = 0; /* mis a 1 pour basculer le mode debug, uniquement dans instr_003 ! */
volatile octet ctx_env_kill = 0; /* mis a 255 si signal de terminaison */
volatile octet ctx_env_debug = 0; /* mis a 1 pour basculer le mode debug, uniquement dans instr_003 ! */
ent64 lap = 0; /* calcul temps du programme (hors init, alloc et free), en ms */
@@ -2140,16 +2140,6 @@ void ntostring(env * e)
}
}
void numstack_printdebug(env * e)
{
printf("num_stack read=%lld lgmax=%lld\n", e->num_stack.read, e->num_stack.lgmax);
for(e->num_stack.write = e->num_stack.read; e->num_stack.write > 0; )
{
e->num_stack.write -= sizeof(number);
printf(" %03lld > %lld\n", e->num_stack.write, *(number *)(e->num_stack.ptr + e->num_stack.write));
}
}
void numstrstack_printdebug(env * e)
{
numstr * pns;
@@ -2277,7 +2267,8 @@ void instr_trace(env * e)
numstrstack_printdebug(e);
callstack_printdebug(e);
hashtable_printdebug(e, &e->g, 1);
/* TODO : env_printdebug */
hashtable_analyze(e, &e->g);
/* */
printf("tmp_free %d tmp_cpt %d\n", e->tmp_free, e->tmp_cpt);
printf("sizeof(env) : %ld\n", (long)sizeof(env));
break;
@@ -2392,18 +2383,12 @@ void instr_007(env * e)
/* => mecanisme realise dans la fonction "decode" */
}
/* */
//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
dynLet(e, &e->int_dynamic, "calc", 4);
printf("part: %d\n", e->part);
if(e->part == 255)
NewProcess(e, &e->int_dynamic);*/
}
/* */
void instr_009(env * e)
@@ -2490,19 +2475,34 @@ void instr_010(env * e)
}
var_free(e, v, FALSE);
/* si objet, memoriser dans _local le pointeur "this" et "parent" */
if(e->ad_var_obj)
if(e->ad_var_obj && e->ad_var_class)
{
var_init(e, &e->int_param, VAR_PARAM, 0, 0, (pointeur)e->ad_var_obj);
v = &e->int_param;
hashtable_do(e, HASH_WRITE, e->local, copy_nom(e, "this"), &v);
hashtable_do(e, HASH_WRITE, e->local, copy_nom(e, GOV_THIS), &v);
//
var_init(e, &e->int_param, VAR_PARAM, 0, 0, (pointeur)e->ad_var_class);
v = &e->int_param;
hashtable_do(e, HASH_WRITE, e->local, copy_nom(e, "parent"), &v);
//
e->ad_var_obj = NULL;
e->ad_var_class = NULL;
e->ad_var = NULL;
if(dynNext(e, e->ad_var_class, &e->tmp_dynamic, cFM) != -1)
{
hashtable_do(e, HASH_READ, &e->g, e->tmp_dynamic.mPtr, &e->ad_var);
if(!e->ad_var || e->ad_var->type != VAR_OBJECT)
e->ad_var = NULL;
}
if(!e->ad_var)
{
/* pas de classe parent (methode dans Base) : parent est une var NULL */
e->v.type = VAR_NULL;
v = &e->v;
}
else
{
var_init(e, &e->int_param, VAR_PARAM, 0, 0, (pointeur)e->ad_var);
v = &e->int_param;
}
hashtable_do(e, HASH_WRITE, e->local, copy_nom(e, GOV_PARENT), &v);
}
e->ad_var_obj = NULL;
e->ad_var_class = NULL;
/* memoriser dans la hash locale : e->si e->si_except e->debut e->fin e->except_ex e->part */
//var_init(e, v, VAR_DYNAMIC, 0, 0, NULL);
v = &e->int_dynamic;
@@ -2906,6 +2906,7 @@ void instr_028(env * e)
{
strncpy(e->nom, (char *)e->si, lg);
e->si += lg;
int parent = nom_is(e, GOV_PARENT);
/* */
if(e->mode_typeof && e->typeof_ == VAR_UNDECLARED) return; /* derniere var inconnue : mode typeof, continuer en attendant le PSHT */
/* */
@@ -2922,6 +2923,7 @@ void instr_028(env * e)
}
if(e->ad_var->type == VAR_PARAM)
{
e->ad_var_dele = e->ad_var; /* memoriser l'adresse de la var PARAM origine, en cas de DELE */
if((e->ad_var = (var *)e->ad_var->ptr) == NULL) /* travailler avec la var pointee ! */
{
e->exception = EX_VARPARAM_KO;
@@ -2932,7 +2934,10 @@ void instr_028(env * e)
}
return;
}
e->ad_var->etat = e->ad_var_dele->etat;
}
else
e->ad_var_dele = NULL;
/* */
if(e->mode_typeof)
{
@@ -2949,6 +2954,27 @@ void instr_028(env * e)
e->ad_var_hash = NULL;
if(e->ad_var->type == VAR_HASHTABLE || e->ad_var->type == VAR_OBJECT)
e->ad_var_hash = e->ad_var;
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
e->ad_var_class = NULL; // dynamic contenant _class de l'objet 'this'
if(e->ad_var->type == VAR_OBJECT && !e->mode_typeof)
{
var * this = NULL;
if(parent && e->local)
{
hashtable_do(e, HASH_READ, e->local, copy_nom(e, GOV_THIS), &this);
if(this && this->type == VAR_PARAM)
this = (var *)this->ptr;
}
/* lire _class mais pas en mode "typeof" */
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &e->ad_var_class);
if(e->ad_var_class)
{
if(parent && this)
e->ad_var_obj = this; /* garder le point de depart initial */
else
e->ad_var_obj = e->ad_var_hash; /* le point de depart est bien un objet/classe */
}
}
}
}
/* */
@@ -3040,6 +3066,15 @@ void instr_029(env * e)
else
e->mode_typeof = FALSE; /* annuler le mode "typeof" si exception autre que var inconnue */
}
else if(e->ad_var_hash && e->ad_var_hash->type == VAR_OBJECT)
{
/* idem PVAR : si objet et pas en mode typeof, lire _class */
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
e->ad_var_class = NULL; // dynamic contenant _class de l'objet 'this'
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &e->ad_var_class);
if(e->ad_var_class)
e->ad_var_obj = e->ad_var_hash; /* le point de depart est bien un objet/classe */
}
return;
}
}
@@ -3409,30 +3444,20 @@ void instr_040(env * e)
e->exception = EX_NOADVAR;
return;
}
/* suppression variable "simple" (que PVAR : locale ou globale) => mis en VARNULL, idem declare */
if(e->ad_var->type == VAR_PARAM)
/* suppression variable "simple" (que PVAR : locale ou globale) => mis en VARNULL, idem declare
la detection de VAR_PARAM (sur ad_var) a ete faite avant dans PVAR */
if(e->ad_var->etat != NULL && e->ad_var_dele != NULL)
{
/* 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 */
/* appartient a une hash : supprimer de la hash et RAZ pointeur (mais pas le nom ici...) */
hashtable_deleteentry(e, (var *)e->ad_var->etat, e->ad_var); /* etat = hash, ad_var = var dans la hash */
/* maj pour remplacer VAR_PARAM, inutilisable, par VAR_NULL */
e->ad_var = e->ad_var_dele; /* VAR_PARAM */
}
/* 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);
var_let(e, e->ad_var, v, FALSE, FALSE);
}
/* */
void instr_041(env * e)
@@ -3604,17 +3629,17 @@ void instr_043(env * e)
/* */
void instr_044(env * e)
{
/* INCL lg nom - onsolete, ne sert plus, a garder pour info dans le compile */
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; }
//
if(lg < 0 || lg > 24)
e->exception = EX_LGNOM;
else if(lg > 0)
e->si += lg;
return;
}
/* INCL lg nom - obsolete, ne sert plus, a garder pour info dans le compile */
//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; }
////
//if(lg < 0 || lg > 24)
// e->exception = EX_LGNOM;
//else if(lg > 0)
// e->si += lg;
//return;
}//
/* */
void instr_045(env * e)
{
@@ -4090,6 +4115,15 @@ void instr_060(env * e)
else
e->mode_typeof = FALSE; /* annuler le mode "typeof" si exception autre que var inconnue */
}
else if(e->ad_var_hash && e->ad_var_hash->type == VAR_OBJECT)
{
/* idem PVAR : si objet et pas en mode typeof, lire _class */
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
e->ad_var_class = NULL; // dynamic contenant _class de l'objet 'this'
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &e->ad_var_class);
if(e->ad_var_class)
e->ad_var_obj = e->ad_var_hash; /* le point de depart est bien un objet/classe */
}
}
}
}
@@ -4147,6 +4181,19 @@ void instr_063(env * e)
e->ad_var->ptr[e->ad_var->mLg++] = c;
e->ad_var->ptr[e->ad_var->mLg] = 0;
}
/* detection erreur dans le cas ou le process est lance par un autre process W => le partage de terminal n'est pas possible sous unix dans ce cas (process cree independant) */
if(c == EOF)
{
int err = errno;
int std_erreur = ferror(stdin);
clearerr(stdin); /* sinon l'erreur reste lors des getchar() suivants */
if(std_erreur && err == EIO) /* si pas EIO sans doute signal (ctrl-c...) */
{
/* erreur, terminal non disponible, pas une fin de saisie/flux */
e->exception = EX_INPUT_TTY;
return;
}
}
}
/* */
void instr_064(env * e)
@@ -4629,7 +4676,7 @@ void instr_077(env * e)
/* PHDO */
/* PHDO <nom> : a partir de <e->ad_var_hash> recherche <nom> (classe + meres) et ad finale de la sub dans <e->ad_var> */
if(e->si > e->fin) { e->exception = EX_END; return; }
int pos = 2, lg = lire8(e->si++);
int lg = lire8(e->si++);
if(e->si + lg - 1 > e->fin) { e->exception = EX_END; return; }
//
if(lg < 1 || lg > 24)
@@ -4637,15 +4684,6 @@ void instr_077(env * e)
e->exception = EX_LGNOM;
return;
}
var * class = NULL;
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
e->ad_var_class = NULL; // hash pour la classe de l'objet : parent (TODO)
if(e->ad_var_hash != NULL)
if(e->ad_var_hash->type == VAR_OBJECT)
{
e->ad_var_obj = e->ad_var_hash;
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &class);
}
e->nom64[0] = 0;
e->nom64[1] = 0;
e->nom64[2] = 0;
@@ -4656,7 +4694,7 @@ void instr_077(env * e)
e->exception = EX_NOADVAR;
return;
}
if(!class)
if( !e->ad_var_obj || !e->ad_var_class)
{
// hash simple : chercher la sub
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
@@ -4664,46 +4702,29 @@ void instr_077(env * e)
e->exception = EX_NAVAR;
return;
}
// classe : chercher dans l'objet courant, puis les classes (doit fonctionner en mode type "classe static")
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
for(; !e->ad_var; pos++)
// objet/classe : chercher dans l'objet courant, puis les classes (doit fonctionner en mode type "classe static")
/* e->ad_var_class contient _class de l'obj */
dynBegin(e, e->ad_var_class);
memset(e->tmp_dynamic.mPtr, 0, 25); /* sinon HASH_READ ko */
while(dynNext(e, e->ad_var_class, &e->tmp_dynamic, cFM) != -1)
{
memset(e->int_dynamic.mPtr, 0, 25);
dynField(e, class, &e->int_dynamic, pos, DYN_NONE, cFM, DYN_NONE, 1);
if(e->int_dynamic.mLg <= 0)
break; // plus de classe dans lesquelles regarder
//
hashtable_do(e, HASH_READ, &e->g, e->int_dynamic.mPtr, &e->ad_var_hash);
if(!e->ad_var_hash)
break; // classe non trouvee
//
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
}
if(e->ad_var)
{
if(e->ad_var->type != VAR_SUBROUTINE)
e->exception = EX_NAVAR;
if(e->tmp_dynamic.mPtr[0] == '0')
e->ad_var_hash = e->ad_var_obj; /* l'oid 0xxxx n'est pas connu comme tel dans e->g */
else
{
// maj pour parent
if(*class->mPtr == '0')
pos = 3; // this pointe sur un objet : mettre la classe mere de la classe de l'objet
else
pos = 2; // this pointe sur une classe : prendre sa mere directe
memset(e->int_dynamic.mPtr, 0, 25);
dynField(e, class, &e->int_dynamic, pos, DYN_NONE, cFM, DYN_NONE, 1);
if(e->int_dynamic.mLg <= 0)
e->exception = EX_NAVAR;
else
{
hashtable_do(e, HASH_READ, &e->g, e->int_dynamic.mPtr, &e->ad_var_class);
if(!e->ad_var_class)
e->exception = EX_NAVAR;
}
}
hashtable_do(e, HASH_READ, &e->g, e->tmp_dynamic.mPtr, &e->ad_var_hash);
if(!e->ad_var_hash || e->ad_var_hash->type != VAR_OBJECT)
break; /* objet/classe non trouve ou pas objet : inutile de continuer */
memset(e->tmp_dynamic.mPtr, 0, 25); /* sinon HASH_READ ko */
/* */
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
if(!e->ad_var)
continue; /* sub non trouve : chercher dans la classe mere suivante */
if(e->ad_var->type != VAR_SUBROUTINE)
break; /* pas une sub : exception, inutile de continuer */
/* trouve, ad_var pointe sur la sub voulue */
return;
}
else
e->exception = EX_NAVAR;
e->exception = EX_NAVAR;
}
/* */
void instr_078(env * e)
@@ -4711,7 +4732,7 @@ void instr_078(env * e)
/* PIDO */
/* PIDO <nom> : a partir de <e->ad_var_hash> recherche <nom> (avec indirection) (classe + meres) et ad finale de la sub dans <e->ad_var> */
if(e->si > e->fin) { e->exception = EX_END; return; }
int pos = 2, lg = lire8(e->si++);
int lg = lire8(e->si++);
if(e->si + lg - 1 > e->fin) { e->exception = EX_END; return; }
//
if(lg < 1 || lg > 24)
@@ -4719,15 +4740,6 @@ void instr_078(env * e)
e->exception = EX_LGNOM;
return;
}
var * class = NULL;
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
e->ad_var_class = NULL; // hash pour la classe de l'objet : parent (TODO)
if(e->ad_var_hash != NULL)
if(e->ad_var_hash->type == VAR_OBJECT)
{
e->ad_var_obj = e->ad_var_hash;
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &class);
}
e->nom64[0] = 0;
e->nom64[1] = 0;
e->nom64[2] = 0;
@@ -4763,7 +4775,7 @@ void instr_078(env * e)
e->nom64[2] = 0;
strncpy(e->nom, v->mPtr, v->lg);
//
if(!class)
if( !e->ad_var_obj || !e->ad_var_class)
{
// hash simple : chercher la sub
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
@@ -4771,46 +4783,29 @@ void instr_078(env * e)
e->exception = EX_NAVAR;
return;
}
// classe : chercher dans l'objet courant, puis les classes (doit fonctionner en mode type "classe static")
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
for(; !e->ad_var; pos++)
// objet/classe : chercher dans l'objet courant, puis les classes (doit fonctionner en mode type "classe static")
/* e->ad_var_class contient _class de l'obj */
dynBegin(e, e->ad_var_class);
memset(e->tmp_dynamic.mPtr, 0, 25); /* sinon HASH_READ ko */
while(dynNext(e, e->ad_var_class, &e->tmp_dynamic, cFM) != -1)
{
memset(e->int_dynamic.mPtr, 0, 25);
dynField(e, class, &e->int_dynamic, pos, DYN_NONE, cFM, DYN_NONE, 1);
if(e->int_dynamic.mLg <= 0)
break; // plus de classe dans lesquelles regarder
//
hashtable_do(e, HASH_READ, &e->g, e->int_dynamic.mPtr, &e->ad_var_hash);
if(!e->ad_var_hash)
break; // classe non trouvee
//
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
}
if(e->ad_var)
{
if(e->ad_var->type != VAR_SUBROUTINE)
e->exception = EX_NAVAR;
if(e->tmp_dynamic.mPtr[0] == '0')
e->ad_var_hash = e->ad_var_obj; /* l'oid 0xxxx n'est pas connu comme tel dans e->g */
else
{
// maj pour parent
if(*class->mPtr == '0')
pos = 3; // this pointe sur un objet : mettre la classe mere de la classe de l'objet
else
pos = 2; // this pointe sur une classe : prendre sa mere directe
memset(e->int_dynamic.mPtr, 0, 25);
dynField(e, class, &e->int_dynamic, pos, DYN_NONE, cFM, DYN_NONE, 1);
if(e->int_dynamic.mLg <= 0)
e->exception = EX_NAVAR;
else
{
hashtable_do(e, HASH_READ, &e->g, e->int_dynamic.mPtr, &e->ad_var_class);
if(!e->ad_var_class)
e->exception = EX_NAVAR;
}
}
hashtable_do(e, HASH_READ, &e->g, e->tmp_dynamic.mPtr, &e->ad_var_hash);
if(!e->ad_var_hash || e->ad_var_hash->type != VAR_OBJECT)
break; /* objet/classe non trouve ou pas objet : inutile de continuer */
memset(e->tmp_dynamic.mPtr, 0, 25); /* sinon HASH_READ ko */
/* */
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
if(!e->ad_var)
continue; /* sub non trouve : chercher dans la classe mere suivante */
if(e->ad_var->type != VAR_SUBROUTINE)
break; /* pas une sub : exception, inutile de continuer */
/* trouve, ad_var pointe sur la sub voulue */
return;
}
else
e->exception = EX_NAVAR;
e->exception = EX_NAVAR;
}
/* */
void instr_079(env * e)
@@ -6406,12 +6401,6 @@ void instr_253(env * e)
else
{
/* dans le demon ici */
// A ESSAYER
chdir("/"); // permet de ne pas bloquer un filesystem avec ce process
setsid(); // nouvelle session
//for(int i = 0;i < FOPEN_MAX; i++)
// close(i); // ferme les fichiers ouverts par le pere
// autre possibilite : rediriger avec dup2 le fichiers 0 1 2 vers /dev/null
e->trace = 0;
e->demon = 1;
}
@@ -6699,7 +6688,7 @@ void (*instr[256])(env * e) = {instr_000,instr_001,instr_002,instr_003,instr_004
; 085 55 DCOF 1 dcount(var)
; 086 56 FIEL 1 fonction "field" : chercher dans la chaine pile1, avec le caractere pile2 (1er car), le champ no pile3, depile + met le resultat
; 087 57 INDX 1 index(var, search, occ)
; 088 58 SRCH 1 search(var) search string in field
; 088 58 SRCH 1 search(var, string) search string in field
; 089 59 CHNG 1 change(var, cherche, remplace)
; 090 5A FMTA 1 format "alignment" (left right center)
; 091 5B INSE 1 insert(var, chaine, field)
@@ -6714,7 +6703,7 @@ void (*instr[256])(env * e) = {instr_000,instr_001,instr_002,instr_003,instr_004
; 100 64 DCOS 1 dcount(var, numchamp)
; 101 65 FMTT 1 format "trim"
; 102 66 FMTS 1 format "surround"
; 103 67 SCHS 1 search(var, numField) search string in subfield of the field given
; 103 67 SCHS 1 search(var, string, numField) search string in subfield of the numField given
; 104 68 INSS 1 insert(var, chaine, field, subfield)
; 105 69 REMS 1 remove(var, field, subfield)
; 106 6A DEXH lg nom 2+lg ad_var_hash.nom<pile1, pile2> = pile3 (suite PHDE)
@@ -6736,8 +6725,8 @@ void (*instr[256])(env * e) = {instr_000,instr_001,instr_002,instr_003,instr_004
; 122 7A HCOU 1 idem PVAH/PVAI mais renvoi le nombre d'element de la hash/objet en cours (dans ad_var = e->int_number)
; 123 7B PVHD lg nom 2+lg enchainement PVAH/PVAI, en dernier supprime dans la hash <ad_var_hash> la var <nom> (idem DELE mais avec suppression)
; 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
; 125 7D SSRC 1 sortedsearch(var, string, sens) search sorted string in field
; 126 7E SSCS 1 sortedsearch(var, string, numField, sens) search sorted string in subfield of the numField given
; 127 7F CPHH 1 idem CPHA mais avec flag positionne indiquant l'empilage d'une var appartenant a une hash
; 128 80 CPHN lg nom 2+lg empile dans la call stack la var ad_var en nommant le parametre <nom> (idem CPAN) et avec flag positionne indiquant l'empilage d'une var appartenant a une hash
;
@@ -6802,6 +6791,7 @@ void trt_sig(int sig)
ctx_env_debug = 1;
return;
case SIGTERM:
case SIGHUP:
case SIGINT:
/* forcer l'arret du process */
ctx_env_kill = IN_ENDP; /* 255 sinon ko */
@@ -6816,7 +6806,7 @@ void init_sig()
sa.sa_flags = 0; /* Pas de SA_RESTART */
sigemptyset(&sa.sa_mask);
signal(SIGHUP, trt_sig); /* 1 */
sigaction(SIGHUP, &sa, NULL); /* 1 */
sigaction(SIGINT, &sa, NULL); /* 2 */
signal(SIGQUIT, trt_sig); /* 3 */
signal(SIGILL, trt_sig); /* 4 */
@@ -6834,12 +6824,12 @@ void init_sig()
signal(SIGUSR1, trt_sig); /* 16 signal utilisateur 1 */
signal(SIGUSR2, trt_sig); /* 17 signal utilisateur 2 */
signal(SIGCHLD, SIG_IGN); /* 18 ATTENTION : permet de ne pas devoir lire l'etat des fils avec wait() !! */
signal(SIGCLD, trt_sig); /* 18 */
/* signal(SIGCLD, trt_sig); */ /* 18 signal duplique */
signal(SIGPWR, trt_sig); /* 19 */
signal(SIGVTALRM, trt_sig); /* 20 */
signal(SIGPROF, trt_sig); /* 21 */
signal(SIGIO, trt_sig); /* 22 */
signal(SIGPOLL, trt_sig); /* 22 */
/* signal(SIGPOLL, trt_sig); */ /* 22 signal duplique */
signal(SIGWINCH, trt_sig);/* 23 */
/* signal(SIGSTOP, trt_sig); */ /* 24 : ne se detourne pas */
signal(SIGTSTP, trt_sig); /* 25 */
@@ -6943,100 +6933,6 @@ void free_sig()
#endif
// EN COURS - mettre dans processMod => non ! car depuis dlsym, risques avec les libs appeles entre fork et execve !
void NewProcess(env * e, var * prog)
{
// <prog> de type DYNAMIC : programme w et ses parametres en VM
if(prog->type != VAR_DYNAMIC)
{
e->exception = EX_NAVAR;
return;
}
var * v;
hashtable_do(e, HASH_READ, &e->g, copy_nom(e, GUV_WARGV), &v);
if(v == NULL) ; /* TODO exception ?! */
/* */
dynIns(e, prog, 1, 1, v, cFM, cVM); /* tester si prog contient un prog w valide ! et ses parametres en MV ! */
dynField(e, v, &e->tmp_dynamic, 1, 1, cFM, cVM, 1);
// Prendre en compte si process en cours est PROG ou BACK (e->demon) + bool en param pour choisir PROG=>BACK (par defaut PROG=>PROG et BACK=>BACK ; BACK=>PROG non autorise)
// ATTENTION : depend du programme lance : si BACK, pas besoin forcement de refaire fork/CreateProcess
#ifndef WINLIB
long pid;
if((pid = fork()) > 0)
{
return; // le pere ne fait rien de plus, apres le lancement du fils
}
else if(pid < 0)
{
e->exception = EX_CHILD_FORK;
return;
}
else
{
/* 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(); /* bloque le meme terminal/console */
//
// si socket retournee par accept, reste ouverte dans le fils : juste envoyer le descripteur
// Appel de shm_lib : newProcessShmWriter()
// TODO
//
printf("avant execvp: %s (%s)\n", e->tmp_dynamic.mPtr, prog->mPtr); // mais param ko dans execvp !
execvp(e->tmp_dynamic.mPtr, dynToTabPtr(e, prog, cVM)); // autre programme, mais garder les autres params de argv, avant le nom du prog wp
// 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(-1);
}
#else
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
// Lancer une nouvelle instance
dynReplace(e, prog, cVM, ' ');
printf("exec win:%s\n", prog->mPtr); // ok
//if (CreateProcess(NULL, v->mPtr, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
if (CreateProcess(NULL, prog->mPtr, NULL, NULL, FALSE, e->demon ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) // CREATE_NEW_CONSOLE ou 0 pour garder la console courante, CREATE_NO_WINDOW phantom (ou DETACHED_PROCESS ?!)
{
// si socket retournee par accept, faire un DuplicateHandle et envoyer le descripteur de la socket
//HANDLE clientSocket = NULL;
//HANDLE dupSocket; // a caster en SOCKET ensuite
//if( ! DuplicateHandle(GetCurrentProcess(), clientSocket, pi.hProcess, &dupSocket, 0, FALSE, DUPLICATE_SAME_ACCESS)) // le handle dupliqué n’a pas besoin d’être héritable
//{
// erreur
//}
// aussi : WSADuplicateSocket puis WSASocket
// Appel de shm_lib : newProcessShmWriter()
// TODO
// Lancer l'execution du process
//ResumeThread(pi.hThread);
// Fermer les handles inutiles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
//printf("Lancement en tache de fond du process, pid %d\n", pi.dwProcessId);
}
else
{
e->exception = EX_CHILD_EXEC;
}
#endif
}
/* si fork : avant exec :
fcntl(sock, F_SETFD, 0); // enlève FD_CLOEXEC, par defaut mettre 1 aux sockets ouverts
*/
/*
int unix_sock = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -7187,7 +7083,6 @@ int CreateContext(env ** ctx, int useSignal, int argc, char *argv[])
var_init(e, &e->int_dynamic, VAR_DYNAMIC, 0, 0, NULL);
var_init(e, &e->tmp_dynamic, VAR_DYNAMIC, 0, 0, NULL);
var_init(e, &e->int_number, VAR_NUMBER, 0, 0, NULL);
var_init(e, &e->num_stack, VAR_BUFFER, 0, 0, NULL);
var_init(e, &e->numstr_stack, VAR_BUFFER, 0, 0, NULL);
var_init(e, &e->call_stack, VAR_BUFFER, 0, 0, NULL);
var_init(e, &e->int_hash, VAR_HASHTABLE, 7, 8, NULL);
@@ -7204,7 +7099,7 @@ int CreateContext(env ** ctx, int useSignal, int argc, char *argv[])
/* verif alloc mem ok */
if(e->g.type == VAR_NULL || e->int_dynamic.type == VAR_NULL || e->int_number.type == VAR_NULL ||
e->numstr_stack.type == VAR_NULL || e->int_hash.type == VAR_NULL || e->tmp_dynamic.type == VAR_NULL ||
e->num_stack.type == VAR_NULL || e->call_stack.type == VAR_NULL || e->debugbrkpoint.type == VAR_NULL ||
e->call_stack.type == VAR_NULL || e->debugbrkpoint.type == VAR_NULL ||
e->debugreglelex.type == VAR_NULL || e->debugcmd.type == VAR_NULL || e->debugvalex.type == VAR_NULL ||
e->printf.type == VAR_NULL)
return (e->except_ex = EX_MEM);
@@ -7335,7 +7230,6 @@ void FreeContext(env * ctx)
var_free(ctx, &ctx->int_dynamic, TRUE);
var_free(ctx, &ctx->tmp_dynamic, TRUE);
var_free(ctx, &ctx->int_number, TRUE);
var_free(ctx, &ctx->num_stack, TRUE);
var_free(ctx, &ctx->call_stack, TRUE);
var_free(ctx, &ctx->numstr_stack, TRUE);
/* ne pas suivre le ptr si <v> ou <int_param> sont des param, donc ptr vers une autre variable, car la pointee a ete desallouee par ailleurs (provoque un bug sous Windows) */
@@ -7591,6 +7485,7 @@ int main(int argc, char *argv[])
{
ent64 cr;
env * ctx_env = NULL;
octet demon = 0;
/* avis de licence */
printf("W language Copyright 2024-2026 lanisys.fr\n");
printf("This program comes with ABSOLUTELY NO WARRANTY;\nThis is free software, and you are welcome to redistribute it\nunder certain conditions (GPL-3.0-or-later)\n\n");
@@ -7626,21 +7521,25 @@ int main(int argc, char *argv[])
A l'init, choix du nom de la CALL externe, 1 seul param, hashtable (!?). Definir le pseudo PROG...
*/
cr = ctx_env->except_ex;
demon = ctx_env->demon;
}
/* */
FreeContext(ctx_env);
/* */
if((cr >> 8) != 0)
cr = EX_EXCEPTNUM;
printf("\nexit:%llu ", cr);
if(cr > 0 && cr <= EXNB)
printf("%s ",strerr[cr - 1]);
if(lap < 1500)
printf("(%llu µs)\n", lap);
else if(lap < 1500000)
printf("(%llu ms)\n", lap/1000);
else
printf("(%llu s)\n", lap/1000000);
if(!demon)
{
printf("\nexit:%llu ", cr);
if(cr > 0 && cr <= EXNB)
printf("%s ",strerr[cr - 1]);
if(lap < 1500)
printf("(%llu µs)\n", lap);
else if(lap < 1500000)
printf("(%llu ms)\n", lap/1000);
else
printf("(%llu s)\n", lap/1000000);
}
exit(cr);
}
@@ -7679,8 +7578,8 @@ int main(int argc, char *argv[])
formule : _srcdbg< (e->bin_indice - 1) * META_NB + 1 > donne le premier attribut pour le source concerne
_class => pour une variable de type objet/classe, variable dynamic ecrite dans la hash de l'objet/classe contenant l'enchainement d'heritage des classes et info si objet instancie
objet : oid FM classe FM classe heritee FM ... FM Base
classe: classe FM classe heritee FM ... FM Base
objet : oid FM classe FM classe heritee FM ... FM 'Base' (avec oid = '0xxxxxx')
classe: classe FM classe heritee FM ... FM 'Base'
_tmpxxx => de _tmp1 a _tmp254 : variables temporaires de type dynamic, creees une fois, servant dans les expressions
+8 -4
View File
@@ -256,12 +256,12 @@ enum {
EX_VARPARAM_KO = 44, /* la variable passee en parametre n'est plus presente en memoire */
EX_PARAM_NOTFOUND = 45, /* la variable passee en parametre est affectee a un nom de parametre inconnu de la sub */
EX_NUMOVF = 46, /* depassement de capacite lors d'un calcul */
EXNB = 46 /* MEMO !!!! */
EX_INPUT_TTY = 47, /* terminal indisponible, lecture entree standard impossible */
EXNB = 47 /* MEMO !!!! */
};
typedef struct env {
/* environnement global */
var num_stack; /* buffers qui contiennent les 2 piles : nombre et appel */
var call_stack; /* mettre les adresses des params dans la call_stack => au debut de la fn, tout est depile ! */
var numstr_stack; /* pile contenant number et string */
var g; /* hashtable qui contient toutes les variables "globales" (begin/end) + objets + vars systemes + modules */
@@ -281,8 +281,9 @@ typedef struct env {
var * ad_var; /* permet de recuperer l'adresse d'une var entre 2 instructions */
var * ad_var_hash; /* dans les enchainements PVAR/PVAH-PVAI, donne l'adresse de la hash possédant la "derniere" variable */
var * ad_var_obj; /* dans une affectation let ou do sub, donne l'objet concerne si objet, pour lire les membres (hors sub) -> pour creer this */
var * ad_var_class; /* donne l'objet de la classe mere de l'objet courant, objet Base si objet de classe Base */
var * ad_var_sav; /* pour memoriser ad_var sur une affectation simple let a.b = c.d, instruction SADV / VLET / PHDV / PIDV */
var * ad_var_class; /* donne l'adresse de la var dynamic _class de l'objet ad_var_obj */
var * ad_var_sav; /* pour memoriser ad_var sur une affectation simple let a.b = c.d, instruction SADV / VLET / PHDV / PIDV / CPHH / CPHN */
var * ad_var_dele; /* memorise ad_var pour DELE */
/* */
ent64 exception; /* exception courante (di) ; 0 ok, si # 0, levee d'une exception et saut au code qui le traite, 0 a chaque debut de fonction */
ent64 except_ex; /* dans bloc except, code erreur ayant genere l'exception ; a mettre a 0 a chaque debut de methode sauf si appel depuis le bloc except ! */
@@ -395,6 +396,9 @@ enum {
#define GUV_BIN "_bin"
#define GUV_WDIR "_wdir"
#define GOV_THIS "this"
#define GOV_PARENT "parent"
#define VARSYS "@varnull,@varnumber,@varsubroutine,@varparam,@vardynamic,@varhashtable,@varobject,@varbuffer,@false,@true,@level,@kill,@oid,@prog,@exceptstr,@exceptline,@except,@part,@line,@os,@vers,@verw,@demon,@endian,@file,@arg,@pi,@fm,@vm,@svm,@tm,@currfm,@currvm,@cr,@lf,@tab,@number,@dynamic,@empty,@trim,@left,@right,@center,@surround,@asc,@desc;1,2,3,4,5,6,7,8,10,11,12,13,14,15,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,50,51,52,53,54,55,56"
#include "global.h"
+9
View File
@@ -393,3 +393,12 @@ WAPIDECL void GetFile(env * e, long lineNumber, Dynamic * meta, int indice, Dyna
*ficLine = lineNumber - dynFieldAsNumber(e, meta, indice + META_GLOBAL_LN, pos, cFM, cVM) + dynFieldAsNumber(e, meta, indice + META_LOCAL_LN, pos, cFM, cVM);
dynField(e, meta, fileFound, indice + META_FILENAME, pos, cFM, cVM, 1);
}
WAPIDECL void GetTempDirectory(env * e, Dynamic * dir)
{
#ifdef WINLIB
dynLet(e, dir, "C:\\Temp\\", DYN_LGNONE);
#else
dynLet(e, dir, "/tmp/", 5);
#endif
}
+2
View File
@@ -40,5 +40,7 @@ WAPIDECL long GetSource(env * e, Dynamic * directory, const char * filename, Dyn
WAPIDECL void GetFile(env * e, long lineNumber, Dynamic * meta, int indice, Dynamic * fileFound, long * ficLine);
WAPIDECL void GetTempDirectory(env * e, Dynamic * dir);
/* ********************************************** */
#endif
+4 -4
View File
@@ -209,9 +209,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
exc = setError(p_etat, EXMOD_SECURESOCK_SERVER_PORT_INVALID); /* en dessous de 1024, necessite des autorisations speciales, non gere ici */
else
{
if(NewSocket(e, &p_etat->ctxSecureSock.ctxSock) == WSOCKET_OK)
if(NewSocket(e, &p_etat->ctxSecureSock.ctxSock, FALSE) == WSOCKET_OK) /* uniquement socket TCP */
{
if(SocketSetServer(e, &p_etat->ctxSecureSock.ctxSock, p_etat->ctxSecureSock.ctxSock.sock, (int)(port / NUM_FACTEUR)) == WSOCKET_OK)
if(SocketSetServer(e, &p_etat->ctxSecureSock.ctxSock, p_etat->ctxSecureSock.ctxSock.sock, (int)(port / NUM_FACTEUR), NULL) == WSOCKET_OK)
{
if(SetPemCertificate(e, &p_etat->ctxSecureSock, paramCertificate, paramPrivateKey) == WSECURESOCKET_OK)
{
@@ -252,9 +252,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
exc = EX_MODPARAM;
else
{
if(NewSocket(e, &p_etat->ctxSecureSock.ctxSock) == WSOCKET_OK)
if(NewSocket(e, &p_etat->ctxSecureSock.ctxSock, FALSE) == WSOCKET_OK) /* uniquement socket TCP */
{
if(SocketConnectToServer(e, &p_etat->ctxSecureSock.ctxSock, p_etat->ctxSecureSock.ctxSock.sock, (int)(port / NUM_FACTEUR), paramHost) == WSOCKET_OK)
if(SocketConnectToServer(e, &p_etat->ctxSecureSock.ctxSock, p_etat->ctxSecureSock.ctxSock.sock, (int)(port / NUM_FACTEUR), NULL, paramHost) == WSOCKET_OK)
{
if(SecureSocketClient(e, &p_etat->ctxSecureSock, p_etat->ctxSecureSock.ctxSock.sock, paramHost, timeout * 1000 / NUM_FACTEUR) == WSECURESOCKET_OK)
{
-3
View File
@@ -68,6 +68,3 @@ WAPIDECL void initShm(env * e, modContextShm * ctx);
WAPIDECL void freeShm(env * e, modContextShm * ctx);
WAPIDECL long readShm(env * e, modContextShm * ctx);
WAPIDECL long writeShm(env * e, modContextShm * ctx);
WAPIDECL long newProcessShmWriter(env * e, modContextShm * ctx);
WAPIDECL long newProcessShmReader(env * e, modContextShm * ctx);
+1 -102
View File
@@ -261,108 +261,7 @@ WAPIDECL long writeShm(env * e, modContextShm * ctx)
return e->exception;
}
WAPIDECL long newProcessShmWriter(env * e, modContextShm * ctx)
{
int sizeLg = 20;
#ifndef WINLIB
key_t cle = Hash32(ctx->desti, 24); // chaine de 23 cars + \0
// acceder au message (type Dynamic, a controler ?)
int handle = shmget(cle, ctx->message->lg + sizeLg, IPC_CREAT | IPC_EXCL | 0666); // < 0 si ko
if(handle < 0)
return EXMOD_BUFFER_WRITE; // erreur access TODO revoir les erreurs
// lire le pointeur
pointeur data = (pointeur)shmat(handle, NULL, 0);
if(data == (pointeur)(-1))
{
shmctl(handle, IPC_RMID, NULL);
return EXMOD_BUFFER_WRITE;
}
// Ecrire les donnees
memset(data, 0, sizeLg);
strcpy((char *)data, Int64ToSz(e, ctx->message->lg, FALSE, sizeLg - 1));
memcpy(data + sizeLg, ctx->message->ptr, ctx->message->lg);
// ne liberer que le ptr sous unix
shmdt(data);
#else
// la cle est directement le destinataire
HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, ctx->message->lg + sizeLg, ctx->desti); // attention au \0 de fin
if( ! handle)
return EXMOD_BUFFER_WRITE; // erreur access
// lire le pointeur
pointeur data = (pointeur)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if( ! data)
{
CloseHandle(handle);
return EXMOD_BUFFER_WRITE; // erreur recup pointeur
}
// Ecrire les donnees
memset(data, 0, sizeLg);
strcpy((char *)data, Int64ToSz(e, ctx->message->lg, FALSE, sizeLg - 1));
memcpy(data + sizeLg, ctx->message->ptr, ctx->message->lg);
// dupliquer le HANDLE sur le mapping
HANDLE dup = NULL;
if( ! DuplicateHandle(GetCurrentProcess(), handle, ctx->newProcess, &dup, 0, FALSE, DUPLICATE_SAME_ACCESS))// FALSE : le handle dupliqué n’a pas besoin d’être héritable
e->exception = EXMOD_BUFFER_WRITE;
// liberations
UnmapViewOfFile(data);
CloseHandle(handle);
#endif
return e->exception;
}
WAPIDECL long newProcessShmReader(env * e, modContextShm * ctx)
{
int sizeLg = 20;
#ifndef WINLIB
key_t cle = Hash32(ctx->desti, 24); // chaine de 23 cars + \0
// acceder au message (type Dynamic, a controler ?)
int handle = shmget(cle, 0, 0); // < 0 si ko
if(handle < 0)
return EXMOD_BUFFER_WRITE; // erreur access TODO revoir les erreurs
// lire le pointeur
pointeur data = (pointeur)shmat(handle, NULL, 0);
if(data == (pointeur)(-1))
{
shmctl(handle, IPC_RMID, NULL);
return EXMOD_BUFFER_WRITE;
}
// Lire les donnees
long err, lg = dynSzToNum(e, (char *)data, FALSE, sizeLg - 1, &err);
if( ! dynCtrl(e, ctx->message, lg, FALSE))
dynSetLen(e, ctx->message, 0);
else
{
dynSetLen(e, ctx->message, lg);
memcpy(data + sizeLg, ctx->message->ptr, ctx->message->lg);
}
// ne liberer que le ptr sous unix
shmdt(data);
shmctl(handle, IPC_RMID, NULL);
#else
// lire le pointeur, a partir du handle lu de la ligne de commande
HANDLE handle = ctx->newProcess;
pointeur data = (pointeur)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if( ! data)
{
CloseHandle(handle);
return EXMOD_BUFFER_WRITE; // erreur recup pointeur
}
// Lire les donnees
long err, lg = dynSzToNum(e, (char *)data, FALSE, sizeLg - 1, &err);
if( ! dynCtrl(e, ctx->message, lg, FALSE))
dynSetLen(e, ctx->message, 0);
else
{
dynSetLen(e, ctx->message, lg);
memcpy(data + sizeLg, ctx->message->ptr, ctx->message->lg);
}
// liberations
UnmapViewOfFile(data);
CloseHandle(handle);
#endif
return e->exception;
}
/* utilite ? */
#ifndef WINLIB
WAPIDECL int OpenLock(env * e, const char * name)
{
+8 -3
View File
@@ -30,6 +30,7 @@
#ifndef WINLIB
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
@@ -42,6 +43,7 @@
#define INVALID_SOCKET -1
#else
#include "winsock2.h" // link avec ws2_32.lib
#include <afunix.h>
#include <windows.h>
typedef SOCKET Socket;
typedef Socket * wPoll;
@@ -61,6 +63,7 @@ enum {
typedef struct {
Dynamic listSocket; // contient le tableau de pollfd/Socket encapsule dans un dynamic
Dynamic localSocket; // chemin de la socket unix locale, vide si socket TCP
int nbSocket; // nombre d'elements dans le tableau de pollfd
int posAddSocket; // endroit ou l'ajout a ete fait dans listSocket
wPoll poll; // pointeur vers le tableau de pollfd/Socket
@@ -77,10 +80,10 @@ typedef struct {
WAPIDECL void initSock(env * e, modContextSocket * ctx);
WAPIDECL void freeSock(env * e, modContextSocket * ctx);
WAPIDECL void SetBlocking(Socket sock, int blocking);
WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx);
WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port);
WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx, int local);
WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port, var * localPath);
WAPIDECL long AcceptClientSocket(env * e, modContextSocket * ctx);
WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * server);
WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * localPath, var * server);
WAPIDECL long AddSocket(env * e, modContextSocket * ctx, Socket sock);
WAPIDECL void DelSocket(env * e, modContextSocket * ctx, Socket sock);
WAPIDECL long WaitSocketForRead(env * e, modContextSocket * ctx, int timeoutMs);
@@ -93,3 +96,5 @@ WAPIDECL int SocketWouldBlock();
WAPIDECL long ReadSocket(env * e, modContextSocket * ctx, Socket sock, var * data, long timeoutMs);
WAPIDECL long WriteSocket(env * e, modContextSocket * ctx, Socket sock, var * data);
WAPIDECL long SendSocket(env * e, modContextSocket * ctx, Socket sock, Socket socketToSend, number pid);
WAPIDECL long ReceiveSocket(env * e, modContextSocket * ctx, Socket sock, Socket * socketReceived);
+116 -4
View File
@@ -28,6 +28,7 @@
#include "langage.h"
#include "dynamic.h"
#include "var.h"
#include "rep.h"
#include <signal.h>
#include <errno.h>
@@ -195,6 +196,7 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
{
/* get param in the right order */
var * paramPortNumber = getParam(e, "portNumber", 10);
/* TODO socket unix locale (pas en mode secure) */
if(paramPortNumber == NULL)
exc = EX_MODPARAM;
else if(paramPortNumber->type != VAR_NUMBER && paramPortNumber->type != VAR_DYNAMIC)
@@ -209,9 +211,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
exc = setError(p_etat, EXMOD_SOCK_SERVER_PORT_INVALID); /* en dessous de 1024, necessite des autorisations speciales, non gere ici */
else
{
if(NewSocket(e, &p_etat->ctxSock) == WSOCKET_OK)
if(NewSocket(e, &p_etat->ctxSock, FALSE) == WSOCKET_OK)
{
if(SocketSetServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, (int)(port / NUM_FACTEUR)) != WSOCKET_OK)
if(SocketSetServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, (int)(port / NUM_FACTEUR), NULL) != WSOCKET_OK)
exc = setError(p_etat, EXMOD_SOCK_SETSERVER);
}
else
@@ -226,6 +228,7 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
var * paramHost = getParam(e, "host", 4);
var * paramPortNumber = getParam(e, "portNumber", 10);
var * paramSocket = getParam(e, "socket", 6);
/* socket unix locale (pas en mode secure) */
if(paramHost == NULL || paramPortNumber == NULL || paramSocket == NULL)
exc = EX_MODPARAM;
else if(paramHost->type != VAR_DYNAMIC || (paramPortNumber->type != VAR_NUMBER && paramPortNumber->type != VAR_DYNAMIC))
@@ -238,9 +241,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
exc = setError(p_etat, EXMOD_SOCK_SERVER_PORT_NUM);
else
{
if(NewSocket(e, &p_etat->ctxSock) == WSOCKET_OK)
if(NewSocket(e, &p_etat->ctxSock, FALSE) == WSOCKET_OK)
{
if(SocketConnectToServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, (int)(port / NUM_FACTEUR), paramHost) == WSOCKET_OK)
if(SocketConnectToServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, (int)(port / NUM_FACTEUR), NULL, paramHost) == WSOCKET_OK)
{
if(paramSocket->type != VAR_NUMBER)
var_let(e, paramSocket, &e->int_number, FALSE, FALSE);
@@ -442,6 +445,115 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
#endif
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "export", 6))
{
/* get param in the right order */
var * paramSocket = getParam(e, "socket", 6);
var * paramPid = getParam(e, "pid", 3);
/* envoi d'une socket a un autre process via son pid, par socket unix locale (non secu) */
if(paramSocket == NULL || paramPid == NULL)
exc = EX_MODPARAM;
else if((paramSocket->type != VAR_NUMBER && paramSocket->type != VAR_DYNAMIC) || (paramPid->type != VAR_NUMBER && paramPid->type != VAR_DYNAMIC))
exc = EX_MODPARAM;
else
{
number socket, pid;
if( ! var_conv_num(e, paramSocket, &socket) || ! var_conv_num(e, paramPid, &pid))
exc = setError(p_etat, EXMOD_SOCK_SERVER_PORT_NUM); // TODO
else
{
if(NewSocket(e, &p_etat->ctxSock, TRUE) == WSOCKET_OK)
{
GetTempDirectory(e, &e->tmp_dynamic);
dynConcatSz(e, &e->tmp_dynamic, "wsocket_", 8);
dynConcatNumber(e, &e->tmp_dynamic, pid);
if(SocketConnectToServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, 0, &e->tmp_dynamic, NULL) == WSOCKET_OK)
{
if(SendSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock, socket, pid) == OK)
{
if(ReadSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock, &e->tmp_dynamic, 1000) == WSOCKET_OK) /* delai 1 sec. */
{
/* verifier si les donnes lues sont egales a "OK" */
/* socket bien recue par l'autre process : fermer celle ici */
FreeSocket(e, &p_etat->ctxSock, socket);
}
else
exc = setError(p_etat, EXMOD_SOCK_READ); // TODO
}
else
exc = setError(p_etat, EXMOD_SOCK_READ); // TODO
FreeSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock);
}
else
exc = setError(p_etat, EXMOD_SOCK_CONNECT); // TODO
}
else
exc = setError(p_etat, EXMOD_SOCK_NEW); // TODO
}
}
}
/* ----------------------------------------------------------------------------------------------- */
else if(modFnIs(e, "import", 6))
{
/* get param in the right order */
var * paramSocket = getParam(e, "socket", 6);
/* recuperation d'une socket depuis un autre process, par socket unix locale (non secu) */
if(paramSocket == NULL)
exc = EX_MODPARAM;
else
{
if(paramSocket->type != VAR_NUMBER)
var_let(e, paramSocket, &e->int_number, FALSE, FALSE);
paramSocket->num = NUM_MOINSUN;
/* */
if(NewSocket(e, &p_etat->ctxSock, TRUE) == WSOCKET_OK)
{
GetTempDirectory(e, &e->tmp_dynamic);
dynConcatSz(e, &e->tmp_dynamic, "wsocket_", 8);
dynConcatNumber(e, &e->tmp_dynamic, getpid());
if(SocketSetServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, 0, &e->tmp_dynamic) == WSOCKET_OK)
{
// couper ici et faire 2 fn : une qui init la socket unix locale, et une qui ecoute et lit une socket
// attend une activite sur la socket serveur et si oui cree une nouvelle socket, timeout 1 seconde en ms
long cr = WaitOneSocketForRead(e, &p_etat->ctxSock, p_etat->ctxSock.servSock, 1000);
if(cr < 0)
exc = setError(p_etat, EXMOD_SOCK_WAIT);
else if(cr == 0)
; /* => timeout, RAS */
else
{
/* nouvelle connexion entrante */
if(AcceptClientSocket(e, &p_etat->ctxSock) == WSOCKET_OK)
{
Socket socket;
if(ReceiveSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock, &socket) == OK)
{
dynLet(e, &e->tmp_dynamic, "OK", 2);
if(WriteSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock, &e->tmp_dynamic) == WSOCKET_OK)
{
/* socket bien recue de l'autre process */
paramSocket->num = socket;
}
else
exc = setError(p_etat, EXMOD_SOCK_WRITE); // TODO
}
else
exc = setError(p_etat, EXMOD_SOCK_READ); // TODO
FreeSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock);
}
else
exc = setError(p_etat, EXMOD_SOCK_ACCEPT);
}
FreeSocket(e, &p_etat->ctxSock, p_etat->ctxSock.servSock); // idem 'stopserver', a separer
}
else
exc = setError(p_etat, EXMOD_SOCK_CONNECT); // TODO
}
else
exc = setError(p_etat, EXMOD_SOCK_NEW); // TODO
}
}
/* ============================================================================================= */
else
{
+267 -69
View File
@@ -43,15 +43,38 @@
/* ---------------------------------------------------- */
/* ****** PRIVATE ************************ */
static void DeleteLocalSocketFile(env * e, modContextSocket * ctx)
{
if(ctx->localSocket.mLg > 0)
#ifndef WINLIB
unlink(ctx->localSocket.mPtr);
#else
DeleteFileA(ctx->localSocket.mPtr);
#endif
dynSetLen(e, &ctx->localSocket, 0);
}
static int SetCloexec(Socket fd)
{
#ifndef WINLIB
int ret = fcntl(fd, F_GETFD);
if(ret != -1)
ret = fcntl(fd, F_SETFD, ret | FD_CLOEXEC);
return (ret == -1); /* TRUE si erreur */
#else
return 0;
#endif
}
/* ****** PUBLIC ************************ */
WAPIDECL void initSock(env * e, modContextSocket * ctx)
{
dynInit(e, &ctx->listSocket, DYN_LGMIN);
dynSetLen(e, &ctx->listSocket, 0); // raz liste sockets
dynInit(e, &ctx->localSocket, DYN_LGMIN);
ctx->servSock = INVALID_SOCKET;
ctx->sock = INVALID_SOCKET;
ctx->packet = 16000;
ctx->packet = 16000; /* parametrable par une fonction ? */
ctx->nbSocket = 0;
//
#ifdef WINLIB
@@ -63,6 +86,8 @@ WAPIDECL void initSock(env * e, modContextSocket * ctx)
WAPIDECL void freeSock(env * e, modContextSocket * ctx)
{
/* fermer les sockets ouvertes */
DeleteLocalSocketFile(e, ctx);
/* */
ctx->poll = (wPoll)ctx->listSocket.ptr;
for(int cpt = 0; cpt < ctx->nbSocket; cpt++)
{
@@ -75,6 +100,7 @@ WAPIDECL void freeSock(env * e, modContextSocket * ctx)
#endif
}
dynFree(e, &ctx->listSocket);
dynFree(e, &ctx->localSocket);
#ifdef WINLIB
WSACleanup();
#endif
@@ -91,8 +117,9 @@ WAPIDECL void SetBlocking(Socket sock, int blocking)
#endif
}
WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx)
WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx, int local)
{
/* local = 1: socket unix, sinon socket TCP */
#ifdef WINLIB
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
@@ -105,14 +132,31 @@ WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx)
struct linger l_s; /* Structure pour setsockopt */
Socket sock;
/* */
#ifndef WINLIB
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
#else
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
#endif
if(local)
{
ctx->err = GetSocketError();
return WSOCKET_ERROR;
/* socket "Unix" (local a une machine) */
#ifndef WINLIB
if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
#else
if((sock = WSASocket(AF_UNIX, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT)) == INVALID_SOCKET)
#endif
{
ctx->err = GetSocketError();
return WSOCKET_ERROR;
}
}
else
{
/* socket TCP */
#ifndef WINLIB
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
#else
if((sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT)) == INVALID_SOCKET)
#endif
{
ctx->err = GetSocketError();
return WSOCKET_ERROR;
}
}
/* */
//#ifndef WINLIB
@@ -120,37 +164,45 @@ WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx)
//#else
//ioctlsocket(sock, FIONBIO, &block_mode);
//#endif
SetCloexec(sock); /* sous Windows, le flag WSA_FLAG_NO_HANDLE_INHERIT fait la meme chose lors du CreateProcess */
/* */
SetBlocking(sock, WSOCKET_NONBLOCKING);
/* */
/* voir ici https://learn.microsoft.com/fr-fr/windows/win32/api/winsock/nf-winsock-setsockopt pour les parametres a passer selon l'option */
#ifndef WINLIB
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt))) /* pour eliminer une erreur : permet de rouvrir des socket suite a fermeture avec des clients encore connectes */
#else
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&bOptVal, bOptLen)) /* pour eliminer une erreur : permet de rouvrir des socket suite a fermeture avec des clients encore connectes */
#endif
if(!local) /* options inutiles en mode socket unix locale */
{
ctx->err = GetSocketError();
/* voir ici https://learn.microsoft.com/fr-fr/windows/win32/api/winsock/nf-winsock-setsockopt pour les parametres a passer selon l'option */
#ifndef WINLIB
close(sock);
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt))) /* pour eliminer une erreur : permet de rouvrir des socket suite a fermeture avec des clients encore connectes */
#else
closesocket(sock);
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&bOptVal, bOptLen)) /* pour eliminer une erreur : permet de rouvrir des socket suite a fermeture avec des clients encore connectes */
#endif
return WSOCKET_ERROR;
}
/* linger n'impacte QUE le close de la socket */
l_s.l_onoff = 1;
l_s.l_linger = 0; // les 2 valeurs provoquent un close avec retour immediat, sans traiter les donnees eventuelles en attente d'envoi et envoi RST au client s'il est connecte en TCP
if(setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&l_s, sizeof (l_s)))
{
ctx->err = GetSocketError();
#ifndef WINLIB
close(sock);
#else
closesocket(sock);
#endif
return WSOCKET_ERROR;
{
ctx->err = GetSocketError();
#ifndef WINLIB
close(sock);
#else
closesocket(sock);
#endif
return WSOCKET_ERROR;
}
/* linger n'impacte QUE le close de la socket */
l_s.l_onoff = 1;
l_s.l_linger = 0; // les 2 valeurs provoquent un close avec retour immediat, sans traiter les donnees eventuelles en attente d'envoi et envoi RST au client s'il est connecte en TCP
if(setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&l_s, sizeof (l_s)))
{
ctx->err = GetSocketError();
#ifndef WINLIB
close(sock);
#else
closesocket(sock);
#endif
return WSOCKET_ERROR;
}
}
/* autres options ?
int flag = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); // demande à TCP d'envoyer les données sans attendre leur regroupement, afin de privilégier la faible latence plutôt que l'efficacité du trafic réseau.
//
int buf = 64000; // de 4 ko a 256 Ko, mais impact tres limite => prevoir plutot un heartbeat applicatif
if(setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&buf, sizeof(buf))) ; // erreur
if(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&buf, sizeof(buf))) ;
@@ -183,18 +235,47 @@ WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx)
return WSOCKET_OK;
}
WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port)
WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port, var * localPath)
{
struct sockaddr_in addr;
//
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
struct sockaddr * sa;
int sofsa;
/* */
dynSetLen(e, &ctx->localSocket, 0);
if(localPath)
{
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
dynSetAs(e, &ctx->localSocket, localPath);
/* localPath doit contenir le chemin complet d'un "fichier" unique pour la socket locale (exemple: /tmp/wsock_1234.sock et C:\\Temp\\wsock_1234.sock) */
if(ctx->localSocket.mLg >= sizeof(addr.sun_path))
{
dynSetLen(e, &ctx->localSocket, 0);
return WSOCKET_ERROR;
}
strcpy(addr.sun_path, ctx->localSocket.mPtr);
/* Supprimer l'ancien fichier de socket s'il existe, sinon le prochain bind echouera */
#ifndef WINLIB
unlink(addr.sun_path);
#else
DeleteFileA(addr.sun_path);
#endif
sa = (struct sockaddr *)&addr;
sofsa = sizeof(addr);
}
else
{
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(port);
sa = (struct sockaddr *)&addr;
sofsa = sizeof(addr);
}
#ifndef WINLIB
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
if(bind(sock, sa, sofsa) < 0)
#else
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
if(bind(sock, sa, sofsa) == SOCKET_ERROR)
#endif
{
ctx->err = GetSocketError();
@@ -203,6 +284,7 @@ WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int
#else
closesocket(sock);
#endif
DeleteLocalSocketFile(e, ctx);
return WSOCKET_ERROR;
}
#ifndef WINLIB
@@ -217,6 +299,7 @@ WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int
#else
closesocket(sock);
#endif
DeleteLocalSocketFile(e, ctx);
return WSOCKET_ERROR;
}
if(AddSocket(e, ctx, sock) == WSOCKET_OK)
@@ -225,7 +308,15 @@ WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int
return WSOCKET_OK;
}
else
{
#ifndef WINLIB
close(sock);
#else
closesocket(sock);
#endif
DeleteLocalSocketFile(e, ctx);
return WSOCKET_ERROR;
}
}
WAPIDECL long AcceptClientSocket(env * e, modContextSocket * ctx)
@@ -259,39 +350,59 @@ WAPIDECL long AcceptClientSocket(env * e, modContextSocket * ctx)
}
}
WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * server)
WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * localPath, var * server)
{
struct sockaddr_in addr;
struct hostent * serv;
//
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
#ifndef WINLIB
if(inet_aton(server->mPtr, &(addr.sin_addr)) == 0)
#else
if(InetPton(AF_INET, server->mPtr, &addr.sin_addr) != 1)
#endif
struct sockaddr * sa;
int sofsa;
/* utilise soit 'localPath' soit 'server' 'port' */
if(localPath)
{
// no ip v4 format, search for name
if((serv = gethostbyname(server->mPtr)) == NULL)
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
dynSetAs(e, &ctx->localSocket, localPath);
/* localPath doit contenir le chemin complet d'un "fichier" unique pour la socket locale (exemple: /tmp/wsock_1234.sock et C:\\Temp\\wsock_1234.sock) */
if(ctx->localSocket.mLg >= sizeof(addr.sun_path))
{
ctx->err = GetSocketError();
#ifndef WINLIB
close(sock);
#else
closesocket(sock);
#endif
dynSetLen(e, &ctx->localSocket, 0);
return WSOCKET_ERROR;
}
//addr.sin_addr.s_addr = ((struct in_addr *)(serv->h_addr))->s_addr;
//addr.sin_addr.s_addr = (*(long *)(serv->h_addr));
memcpy(&addr.sin_addr, serv->h_addr_list[0], serv->h_length);
strcpy(addr.sun_path, ctx->localSocket.mPtr); /* la gestion du fichier socket local est laisse a la gestion du socket serveur en ecoute */
sa = (struct sockaddr *)&addr;
sofsa = sizeof(addr);
}
/* laisser en bloquant (tout le temps) et gerer la pseudo erreur
"EINPROGRESS/EWOULDBLOCK" => attendre ici que socket ok en ecriture
*/
int ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
else
{
struct sockaddr_in addr;
struct hostent * serv;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
#ifndef WINLIB
if(inet_aton(server->mPtr, &(addr.sin_addr)) == 0)
#else
if(InetPton(AF_INET, server->mPtr, &addr.sin_addr) != 1)
#endif
{
// no ip v4 format, search for name
if((serv = gethostbyname(server->mPtr)) == NULL)
{
ctx->err = GetSocketError();
#ifndef WINLIB
close(sock);
#else
closesocket(sock);
#endif
return WSOCKET_ERROR;
}
//addr.sin_addr.s_addr = ((struct in_addr *)(serv->h_addr))->s_addr;
//addr.sin_addr.s_addr = (*(long *)(serv->h_addr));
memcpy(&addr.sin_addr, serv->h_addr_list[0], serv->h_length);
}
sa = (struct sockaddr *)&addr;
sofsa = sizeof(addr);
}
/* laisser en non bloquant */
int ret = connect(sock, sa, sofsa);
#ifdef WINLIB
if (ret == SOCKET_ERROR)
{
@@ -346,6 +457,91 @@ WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock
return WSOCKET_OK;
}
WAPIDECL long SendSocket(env * e, modContextSocket * ctx, Socket sock, Socket socketToSend, number pid)
{
/* send socket using AF_UNIX local socket */
#ifndef WINLIB
struct msghdr msg = {0};
char buffer[CMSG_SPACE(sizeof(int))];
memset(buffer, 0, sizeof(buffer));
struct iovec io = {
.iov_base = (void *)"X", /* peu importe... */
.iov_len = 1
};
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = buffer;
msg.msg_controllen = sizeof(buffer);
struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg);
if(cmsg == NULL)
return -1;
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsg), &socketToSend, sizeof(socketToSend));
if(sendmsg(sock, &msg, 0) < 0)
return -1;
else
return OK;
/* */
#else
WSAPROTOCOL_INFO info = {0};
if(WSADuplicateSocket(socketToSend, pid, &info) == SOCKET_ERROR)
return -1;
var * v = &e->tmp_dynamic; // verifier que v assez grand pour info
if(dynCtrl(e, v, sizeof(info), FALSE))
return -1;
memcpy(v->ptr, &info, sizeof(info));
v->mLg = sizeof(info);
if(WriteSocket(e, ctx, sock, v) != WSOCKET_OK)
return -1;
else
return OK;
#endif
}
WAPIDECL long ReceiveSocket(env * e, modContextSocket * ctx, Socket sock, Socket * socketReceived)
{
/* receive socket from AF_UNIX local socket */
#ifndef WINLIB
struct msghdr msg = {0};
char buffer[CMSG_SPACE(sizeof(int))];
memset(buffer, 0, sizeof(buffer));
struct iovec io = {
.iov_base = (void *)"X", /* peu importe... */
.iov_len = sizeof(1)
};
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = buffer;
msg.msg_controllen = sizeof(buffer);
if(recvmsg(sock, &msg, 0) <= 0)
return -1;
if(msg.msg_flags & MSG_CTRUNC)
return -1;
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if(cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS || cmsg->cmsg_len < CMSG_LEN(sizeof(int)))
return -1; /* pas de socket valide recue */
memcpy(socketReceived, CMSG_DATA(cmsg), sizeof(*socketReceived));
return OK;
/* */
#else
var * v = &e->tmp_dynamic;
dynSetLen(e, v, 0);
if(ReadSocket(e, ctx, sock, v, 1000) != WSOCKET_OK) // 1 sec.
return -1;
WSAPROTOCOL_INFO info = {0};
if(v->mLg != sizeof(info))
return -1;
memcpy(&info, v->ptr, sizeof(info));
*socketReceived = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &info, 0, 0);
if(*socketReceived == INVALID_SOCKET)
return -1;
else
return OK;
#endif
}
WAPIDECL long AddSocket(env * e, modContextSocket * ctx, Socket sock)
{
#ifndef WINLIB
@@ -499,7 +695,7 @@ WAPIDECL long WaitOneSocketForWrite(env * e, modContextSocket * ctx, Socket sock
WAPIDECL void FreeSocket(env * e, modContextSocket * ctx, Socket sock)
{
/* supprimer le fichier d'un socket unix (local) - uniquement au moment de la liberation du socket serveur en ecoute */
#ifndef WINLIB
shutdown(sock, SHUT_RDWR); // inutile a cause de SO_LINGER = 1 !?
close(sock);
@@ -507,6 +703,8 @@ WAPIDECL void FreeSocket(env * e, modContextSocket * ctx, Socket sock)
shutdown(sock, SD_BOTH); // inutile a cause de SO_LINGER = 1 !?
closesocket(sock);
#endif
if(sock == ctx->servSock)
DeleteLocalSocketFile(e, ctx);
DelSocket(e, ctx, sock);
}
+15
View File
@@ -26,6 +26,7 @@
#include <WinSock2.h>
#else
#include "poll.h"
#include <fcntl.h>
#endif
// force exporting
@@ -110,6 +111,19 @@ int ssh_read_timeout(env * e, modContextSsh * ctx, Dynamic * data, number timeou
return ssh_channel_read(ctx->channel, data->mPtr + data->mLg, ctx->packet, 0); /* 0 signifie lire stdout, 1 pour stderr */
}
static int setSessionCloexec(ssh_session session)
{
#ifndef WINLIB
int fd = (int)ssh_get_fd(session);
int ret = fcntl(fd, F_GETFD);
if(ret != -1)
ret = fcntl(fd, F_SETFD, ret | FD_CLOEXEC);
return (ret == -1); /* TRUE si erreur */
#else
return 0;
#endif
}
/* ****** PUBLIC ************************ */
WAPIDECL void initSsh(env * e, modContextSsh * ctx)
{
@@ -140,6 +154,7 @@ WAPIDECL long setSession(env * e, modContextSsh * ctx, Dynamic * host, Dynamic
ctx->session = NULL;
return (ctx->err = WSSH_SESSION_CONNECT);
}
setSessionCloexec(ctx->session); /* permet fork + execv securises, une fois connecte */
/* */
if(ssh_userauth_password(ctx->session, NULL, pwd->mPtr) != SSH_AUTH_SUCCESS)
{
+68 -2
View File
@@ -28,6 +28,7 @@
#include "langage.h"
#include "dynamic.h"
#include "var.h"
#include "hashtable.h"
#ifdef WINLIB
#include "windows.h"
@@ -54,7 +55,8 @@ enum {
EXMOD_SYSTEM_SETENV = 3,
EXMOD_SYSTEM_UNSETENV = 4,
EXMOD_SYSTEM_UNAME = 5,
EXMOD_NB = 5
EXMOD_CMDLINE_ARG = 6,
EXMOD_NB = 6
};
/* libelles des codes d'erreur, qui doivent aller de 1 a EXMOD_NB */
char * descModErr[] = {
@@ -63,7 +65,8 @@ char * descModErr[] = {
"Unknown environment variable",
"set environment variable error",
"delete environment variable error",
"Cannot get host name" // 5
"Cannot get host name", // 5
"Cannot read command line arguments"
};
/* ============================================================================================= */
@@ -445,6 +448,69 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
exc = EX_MODPARAM;
}
}
else if(modFnIs(e, "newProcess", 10))
{
/* get param in the right order */
var * paramArgs = getParam(e, "args", 4);
var * paramPid = getParam(e, "newPid", 6);
if(paramArgs == NULL || paramPid == NULL)
exc = EX_MODPARAM;
else if(paramArgs->type != VAR_DYNAMIC) /* progs w + arguments en FM */
exc = EX_MODPARAM;
else
{
if(paramPid->type != VAR_NUMBER)
var_let(e, paramPid, &e->int_number, FALSE, FALSE);
paramPid->num = 0; /* erreur par defaut */
/* lire GUV_ENV et GUV_WARGV{1} pour reconstituer la ligne de commande windows/unix */
var * va = &e->int_dynamic;
hashtable_do(e, HASH_READ, &e->g, copy_nom(e, GUV_WARGV), &va); // garder {1,1} = executeur W
var * ve = &e->tmp_dynamic;
hashtable_do(e, HASH_READ, &e->g, copy_nom(e, GUV_ENV), &ve); // wbin wsrc wlib {1,1-3}
if(va && ve)
{
dynStore(e, va, 2, DYN_NONE, ve, cVM, DYN_NONE);
dynField(e, va, ve, 1, DYN_NONE, cVM, DYN_NONE, 4); /* ve = execw wbin wsrc wlib en VM */
dynReplace(e, ve, cVM, cFM);
dynConcatSz(e, ve, sFM, 1);
dynConcat(e, ve, paramArgs); /* ve = execw wbin wsrc wlib progw argw1 etc. en FM */
dynInsSz(e, ve, 2, 1, "-WBIN", 5, cFM, ':');
dynInsSz(e, ve, 3, 1, "-WSRC", 5, cFM, ':');
dynInsSz(e, ve, 4, 1, "-WLIB", 5, cFM, ':');
/* ve (tmp_dynamic) contient la ligne de commande complete */
#ifdef WINLIB
dynReplace(e, ve, cFM, ' '); /* recree une ligne de commande */
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(si);
if(CreateProcess(NULL, ve->mPtr, NULL, NULL, FALSE, e->demon ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) // ou DETACHED_PROCESS comme avec BACK !?
{
paramPid->num = pi.dwProcessId * NUM_FACTEUR; /* ok, code retour = pid du process cree */
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
#else
long pid = fork();
if(pid > 0)
{
/* dans le pere, retourner le pid du process cree */
paramPid->num = pid * NUM_FACTEUR;
}
else if(pid == 0)
{
/* dans le fils : execvp et sortie */
dynField(e, ve, va, 1, DYN_NONE, cFM, DYN_NONE, 1);
char ** argv = dynToTabPtr(e, ve, cFM);
execvp(va->mPtr, argv); /* attention : si programme interactif en front lance (cas exec 'calc') avec acces entree standard => generera une exception car ce n'est pas possible sous Unix (ok windows) */
/* ici, erreur de execvp */
_exit(127); /* mieux que exit(0) !? */
}
#endif
}
else
exc = setError(p_etat, EXMOD_CMDLINE_ARG);
}
}
/* ============================================================================================= */
else
{
+4 -1
View File
@@ -287,7 +287,7 @@ WAPIDECL void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v)
}
}
// liberation variable affectee
var_free(e, let, TRUE);
var_free(e, let, FALSE); /* let pointe sur la vraie var si VAR_PARAM et suivre */
// init et copie
switch(v->type)
{
@@ -315,7 +315,10 @@ WAPIDECL void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v)
//
case VAR_PARAM:
if(!suivre_v) // ??
{
var_init(e, let, VAR_PARAM, 0, 0, v->ptr);
let->etat = v->etat;
}
break;
case VAR_BUFFER: