"Fossies" - the Fresh Open Source Software Archive

Member "singular-4.2.1/Singular/links/ssiLink.cc" (9 Jun 2021, 61306 Bytes) of package /linux/misc/singular-4.2.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ssiLink.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.2.0p3_vs_4.2.1.

    1 /****************************************
    2  * Computer Algebra System SINGULAR     *
    3  ****************************************/
    4 /***************************************************************
    5  * File:    ssiLink.h
    6  *  Purpose: declaration of sl_link routines for ssi
    7  ***************************************************************/
    8 #define TRANSEXT_PRIVATES 1 /* allow access to transext internals */
    9 
   10 #include "kernel/mod2.h"
   11 
   12 #include "misc/intvec.h"
   13 #include "misc/options.h"
   14 
   15 #include "reporter/si_signals.h"
   16 #include "reporter/s_buff.h"
   17 
   18 #include "coeffs/bigintmat.h"
   19 #include "coeffs/longrat.h"
   20 
   21 #include "polys/monomials/ring.h"
   22 #include "polys/monomials/p_polys.h"
   23 #include "polys/ext_fields/transext.h"
   24 #include "polys/simpleideals.h"
   25 #include "polys/matpol.h"
   26 
   27 #include "kernel/oswrapper/timer.h"
   28 #include "kernel/oswrapper/feread.h"
   29 #include "kernel/oswrapper/rlimit.h"
   30 
   31 #include "Singular/tok.h"
   32 #include "Singular/ipid.h"
   33 #include "Singular/ipshell.h"
   34 #include "Singular/subexpr.h"
   35 #include "Singular/links/silink.h"
   36 #include "Singular/cntrlc.h"
   37 #include "Singular/feOpt.h"
   38 #include "Singular/lists.h"
   39 #include "Singular/blackbox.h"
   40 #include "Singular/links/ssiLink.h"
   41 
   42 #ifdef HAVE_SIMPLEIPC
   43 #include "Singular/links/simpleipc.h"
   44 #endif
   45 
   46 #include <errno.h>
   47 #include <sys/types.h>          /* for portability */
   48 #include <ctype.h>   /*for isdigit*/
   49 #include <netdb.h>
   50 #include <netinet/in.h> /* for htons etc.*/
   51 
   52 #define SSI_VERSION 13
   53 // 5->6: changed newstruct representation
   54 // 6->7: attributes
   55 // 7->8: qring
   56 // 8->9: module: added rank
   57 // 9->10: tokens in grammar.h/tok.h reorganized
   58 // 10->11: extended ring descr. for named coeffs (not in used until 4.1)
   59 // 11->12: add rank to ideal/module, add smatrix
   60 // 12->13: NC rings
   61 
   62 VAR link_list ssiToBeClosed=NULL;
   63 VAR volatile BOOLEAN ssiToBeClosed_inactive=TRUE;
   64 
   65 // forward declarations:
   66 void ssiWritePoly_R(const ssiInfo *d, int typ, poly p, const ring r);
   67 void ssiWriteIdeal_R(const ssiInfo *d, int typ,const ideal I, const ring r);
   68 poly ssiReadPoly_R(const ssiInfo *D, const ring r);
   69 ideal ssiReadIdeal_R(const ssiInfo *d,const ring r);
   70 
   71 // the helper functions:
   72 BOOLEAN ssiSetCurrRing(const ring r) /* returned: not accepted */
   73 {
   74   //  if (currRing!=NULL)
   75   //  Print("need to change the ring, currRing:%s, switch to: ssiRing%d\n",IDID(currRingHdl),nr);
   76   //  else
   77   //  Print("no ring, switch to ssiRing%d\n",nr);
   78   if (r==currRing)
   79   {
   80     rIncRefCnt(r);
   81     currRingHdl=rFindHdl(r,currRingHdl);
   82     return TRUE;
   83   }
   84   else if ((currRing==NULL) || (!rEqual(r,currRing,1)))
   85   {
   86     char name[20];
   87     int nr=0;
   88     idhdl h=NULL;
   89     loop
   90     {
   91       sprintf(name,"ssiRing%d",nr); nr++;
   92       h=IDROOT->get(name, 0);
   93       if (h==NULL)
   94       {
   95         h=enterid(name,0,RING_CMD,&IDROOT,FALSE);
   96         IDRING(h)=rIncRefCnt(r);
   97         r->ref=2;/*ref==2: d->r and h */
   98         break;
   99       }
  100       else if ((IDTYP(h)==RING_CMD)
  101       && (rEqual(r,IDRING(h),1)))
  102       {
  103         rIncRefCnt(IDRING(h));
  104         break;
  105       }
  106     }
  107     rSetHdl(h);
  108     return FALSE;
  109   }
  110   else
  111   {
  112     rKill(r);
  113     rIncRefCnt(currRing);
  114     return TRUE;
  115   }
  116 }
  117 void ssiCheckCurrRing(const ring r)
  118 {
  119   if ((r!=currRing)
  120   ||(currRingHdl==NULL)
  121   ||(IDRING(currRingHdl)!=r))
  122   {
  123     char name[20];
  124     int nr=0;
  125     idhdl h=NULL;
  126     loop
  127     {
  128       sprintf(name,"ssiRing%d",nr); nr++;
  129       h=IDROOT->get(name, 0);
  130       if (h==NULL)
  131       {
  132         h=enterid(name,0,RING_CMD,&IDROOT,FALSE);
  133         IDRING(h)=rIncRefCnt(r);
  134         r->ref=2;/*ref==2: d->r and h */
  135         break;
  136       }
  137       else if ((IDTYP(h)==RING_CMD)
  138       && (rEqual(r,IDRING(h),1)))
  139       {
  140         break;
  141       }
  142     }
  143     rSetHdl(h);
  144   }
  145   assume((currRing==r) || rEqual(r,currRing));
  146 }
  147 // the implementation of the functions:
  148 void ssiWriteInt(const ssiInfo *d,const int i)
  149 {
  150   fprintf(d->f_write,"%d ",i);
  151   //if (d->f_debug!=NULL) fprintf(d->f_debug,"int: %d ",i);
  152 }
  153 
  154 void ssiWriteString(const ssiInfo *d,const char *s)
  155 {
  156   fprintf(d->f_write,"%d %s ",(int)strlen(s),s);
  157   //if (d->f_debug!=NULL) fprintf(d->f_debug,"stringi: %d \"%s\" ",strlen(s),s);
  158 }
  159 
  160 void ssiWriteBigInt(const ssiInfo *d, const number n)
  161 {
  162  n_WriteFd(n,d,coeffs_BIGINT);
  163 }
  164 
  165 void ssiWriteNumber_CF(const ssiInfo *d, const number n, const coeffs cf)
  166 {
  167   // syntax is as follows:
  168   // case 1 Z/p:   3 <int>
  169   // case 2 Q:     3 4 <int>
  170   //        or     3 0 <mpz_t nominator> <mpz_t denominator>
  171   //        or     3 1  dto.
  172   //        or     3 3 <mpz_t nominator>
  173   //        or     3 5 <mpz_t raw nom.> <mpz_t raw denom.>
  174   //        or     3 6 <mpz_t raw nom.> <mpz_t raw denom.>
  175   //        or     3 8 <mpz_t raw nom.>
  176   if (getCoeffType(cf)==n_transExt)
  177   {
  178     fraction f=(fraction)n;
  179     ssiWritePoly_R(d,POLY_CMD,NUM(f),cf->extRing);
  180     ssiWritePoly_R(d,POLY_CMD,DEN(f),cf->extRing);
  181   }
  182   else if (getCoeffType(cf)==n_algExt)
  183   {
  184     ssiWritePoly_R(d,POLY_CMD,(poly)n,cf->extRing);
  185   }
  186   else if (cf->cfWriteFd!=NULL)
  187   {
  188     n_WriteFd(n,d,cf);
  189   }
  190   else WerrorS("coeff field not implemented");
  191 }
  192 
  193 void ssiWriteNumber(const ssiInfo *d, const number n)
  194 {
  195   ssiWriteNumber_CF(d,n,d->r->cf);
  196 }
  197 
  198 void ssiWriteRing_R(ssiInfo *d,const ring r)
  199 {
  200   /* 5 <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... <extRing> <Q-ideal> */
  201   /* ch=-1: transext, coeff ring follows */
  202   /* ch=-2: algext, coeff ring and minpoly follows */
  203   /* ch=-3: cf name follows */
  204   if (r!=NULL)
  205   {
  206     if (rField_is_Q(r) || rField_is_Zp(r))
  207       fprintf(d->f_write,"%d %d ",n_GetChar(r->cf),r->N);
  208     else if (rFieldType(r)==n_transExt)
  209       fprintf(d->f_write,"-1 %d ",r->N);
  210     else if (rFieldType(r)==n_algExt)
  211       fprintf(d->f_write,"-2 %d ",r->N);
  212     else /*dummy*/
  213     {
  214       fprintf(d->f_write,"-3 %d ",r->N);
  215       ssiWriteString(d,nCoeffName(r->cf));
  216     }
  217 
  218     int i;
  219     for(i=0;i<r->N;i++)
  220     {
  221       fprintf(d->f_write,"%d %s ",(int)strlen(r->names[i]),r->names[i]);
  222     }
  223     /* number of orderings:*/
  224     i=0;
  225     // remember dummy ring: everything 0:
  226     if (r->order!=NULL) while (r->order[i]!=0) i++;
  227     fprintf(d->f_write,"%d ",i);
  228     /* each ordering block: */
  229     i=0;
  230     if (r->order!=NULL) while(r->order[i]!=0)
  231     {
  232       fprintf(d->f_write,"%d %d %d ",r->order[i],r->block0[i], r->block1[i]);
  233       switch(r->order[i])
  234       {
  235         case ringorder_a:
  236         case ringorder_wp:
  237         case ringorder_Wp:
  238         case ringorder_ws:
  239         case ringorder_Ws:
  240         case ringorder_aa:
  241         {
  242           int ii;
  243           for(ii=r->block0[i];ii<=r->block1[i];ii++)
  244             fprintf(d->f_write,"%d ",r->wvhdl[i][ii-r->block0[i]]);
  245         }
  246         break;
  247 
  248         case ringorder_a64:
  249         case ringorder_M:
  250         case ringorder_L:
  251         case ringorder_IS:
  252           Werror("ring oder not implemented for ssi:%d",r->order[i]);
  253           break;
  254 
  255         default: break;
  256       }
  257       i++;
  258     }
  259     if ((rFieldType(r)==n_transExt)
  260     || (rFieldType(r)==n_algExt))
  261     {
  262       ssiWriteRing_R(d,r->cf->extRing); /* includes alg.ext if rFieldType(r)==n_algExt */
  263     }
  264     /* Q-ideal :*/
  265     if (r->qideal!=NULL)
  266     {
  267       ssiWriteIdeal_R(d,IDEAL_CMD,r->qideal,r);
  268     }
  269     else
  270     {
  271       fputs("0 ",d->f_write/*ideal with 0 entries */);
  272     }
  273   }
  274   else /* dummy ring r==NULL*/
  275   {
  276     fputs("0 0 0 0 "/*,r->ch,r->N, blocks, q-ideal*/,d->f_write);
  277   }
  278   if (rIsLPRing(r)) // cannot be combined with 23 2
  279   {
  280     fprintf(d->f_write,"23 1 %d %d ",SI_LOG2(r->bitmask),r->isLPring);
  281   }
  282   else
  283   {
  284     unsigned long bm=0;
  285     int b=0;
  286     bm=rGetExpSize(bm,b,r->N);
  287     if (r->bitmask!=bm)
  288     {
  289       fprintf(d->f_write,"23 0 %d ",SI_LOG2(r->bitmask));
  290     }
  291     if (rIsPluralRing(r))
  292     {
  293       fputs("23 2 ",d->f_write);
  294       void ssiWriteIdeal(const ssiInfo *d, int typ,const ideal I);
  295       ssiWriteIdeal(d,MATRIX_CMD,(ideal)r->GetNC()->C);
  296       ssiWriteIdeal(d,MATRIX_CMD,(ideal)r->GetNC()->D);
  297     }
  298   }
  299 }
  300 
  301 void ssiWriteRing(ssiInfo *d,const ring r)
  302 {
  303   /* 5 <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... <extRing> <Q-ideal> */
  304   /* ch=-1: transext, coeff ring follows */
  305   /* ch=-2: algext, coeff ring and minpoly follows */
  306   /* ch=-3: cf name follows */
  307   /* ch=-4: NULL */
  308   if ((r==NULL)||(r->cf==NULL))
  309   {
  310     fputs("-4 ",d->f_write);
  311     return;
  312   }
  313   if (r==currRing) // see recursive calls for transExt/algExt
  314   {
  315     if (d->r!=NULL) rKill(d->r);
  316     d->r=r;
  317   }
  318   if (r!=NULL)
  319   {
  320     /*d->*/rIncRefCnt(r);
  321   }
  322   ssiWriteRing_R(d,r);
  323 }
  324 void ssiWritePoly_R(const ssiInfo *d, int /*typ*/, poly p, const ring r)
  325 {
  326   fprintf(d->f_write,"%d ",pLength(p));//number of terms
  327 
  328   while(p!=NULL)
  329   {
  330     ssiWriteNumber_CF(d,pGetCoeff(p),r->cf);
  331     //nWrite(fich,pGetCoeff(p));
  332     fprintf(d->f_write,"%ld ",p_GetComp(p,r));//component
  333 
  334     for(int j=1;j<=rVar(r);j++)
  335     {
  336       fprintf(d->f_write,"%ld ",p_GetExp(p,j,r ));//x^j
  337     }
  338     pIter(p);
  339   }
  340 }
  341 
  342 void ssiWritePoly(const ssiInfo *d, int typ, poly p)
  343 {
  344   ssiWritePoly_R(d,typ,p,d->r);
  345 }
  346 
  347 void ssiWriteIdeal_R(const ssiInfo *d, int typ,const ideal I, const ring R)
  348 {
  349    // syntax: 7 # of elements <poly 1> <poly2>.....(ideal,module,smatrix)
  350    // syntax: 8 <rows> <cols> <poly 1> <poly2>.....(matrix)
  351    // syntax
  352    matrix M=(matrix)I;
  353    int mn;
  354    if (typ==MATRIX_CMD)
  355    {
  356      mn=MATROWS(M)*MATCOLS(M);
  357      fprintf(d->f_write,"%d %d ", MATROWS(M),MATCOLS(M));
  358    }
  359    else
  360    {
  361      mn=IDELEMS(I);
  362      fprintf(d->f_write,"%d ",IDELEMS(I));
  363    }
  364 
  365    int i;
  366    int tt;
  367    if ((typ==MODUL_CMD)||(typ==SMATRIX_CMD))
  368      tt=VECTOR_CMD;
  369    else
  370      tt=POLY_CMD;
  371 
  372    for(i=0;i<mn;i++)
  373    {
  374      ssiWritePoly_R(d,tt,I->m[i],R);
  375    }
  376 }
  377 void ssiWriteIdeal(const ssiInfo *d, int typ,const ideal I)
  378 {
  379   ssiWriteIdeal_R(d,typ,I,d->r);
  380 }
  381 
  382 void ssiWriteCommand(si_link l, command D)
  383 {
  384   ssiInfo *d=(ssiInfo*)l->data;
  385   // syntax: <num ops> <operation> <op1> <op2> ....
  386   fprintf(d->f_write,"%d %d ",D->argc,D->op);
  387   if (D->argc >0) ssiWrite(l, &(D->arg1));
  388   if (D->argc < 4)
  389   {
  390     if (D->argc >1) ssiWrite(l, &(D->arg2));
  391     if (D->argc >2) ssiWrite(l, &(D->arg3));
  392   }
  393 }
  394 
  395 void ssiWriteProc(const ssiInfo *d,procinfov p)
  396 {
  397   if (p->data.s.body==NULL)
  398     iiGetLibProcBuffer(p);
  399   if (p->data.s.body!=NULL)
  400     ssiWriteString(d,p->data.s.body);
  401   else
  402     ssiWriteString(d,"");
  403 }
  404 
  405 void ssiWriteList(si_link l,lists dd)
  406 {
  407   ssiInfo *d=(ssiInfo*)l->data;
  408   int Ll=dd->nr;
  409   fprintf(d->f_write,"%d ",Ll+1);
  410   int i;
  411   for(i=0;i<=Ll;i++)
  412   {
  413     ssiWrite(l,&(dd->m[i]));
  414   }
  415 }
  416 void ssiWriteIntvec(const ssiInfo *d,intvec * v)
  417 {
  418   fprintf(d->f_write,"%d ",v->length());
  419   int i;
  420   for(i=0;i<v->length();i++)
  421   {
  422     fprintf(d->f_write,"%d ",(*v)[i]);
  423   }
  424 }
  425 void ssiWriteIntmat(const ssiInfo *d,intvec * v)
  426 {
  427   fprintf(d->f_write,"%d %d ",v->rows(),v->cols());
  428   int i;
  429   for(i=0;i<v->length();i++)
  430   {
  431     fprintf(d->f_write,"%d ",(*v)[i]);
  432   }
  433 }
  434 
  435 void ssiWriteBigintmat(const ssiInfo *d,bigintmat * v)
  436 {
  437   fprintf(d->f_write,"%d %d ",v->rows(),v->cols());
  438   int i;
  439   for(i=0;i<v->length();i++)
  440   {
  441     ssiWriteBigInt(d,(*v)[i]);
  442   }
  443 }
  444 
  445 char *ssiReadString(const ssiInfo *d)
  446 {
  447   char *buf;
  448   int l;
  449   l=s_readint(d->f_read);
  450   buf=(char*)omAlloc0(l+1);
  451   int throwaway =s_getc(d->f_read); /* skip ' '*/
  452   throwaway=s_readbytes(buf,l,d->f_read);
  453   //if (throwaway!=l) printf("want %d, got %d bytes\n",l,throwaway);
  454   buf[l]='\0';
  455   return buf;
  456 }
  457 
  458 int ssiReadInt(s_buff fich)
  459 {
  460   return s_readint(fich);
  461 }
  462 
  463 number ssiReadNumber_CF(const ssiInfo *d, const coeffs cf)
  464 {
  465   if (cf->cfReadFd!=NULL)
  466   {
  467      return n_ReadFd(d,cf);
  468   }
  469   else if (getCoeffType(cf) == n_transExt)
  470   {
  471     // poly poly
  472     fraction f=(fraction)n_Init(1,cf);
  473     p_Delete(&NUM(f),cf->extRing);
  474     NUM(f)=ssiReadPoly_R(d,cf->extRing);
  475     DEN(f)=ssiReadPoly_R(d,cf->extRing);
  476     return (number)f;
  477   }
  478   else if (getCoeffType(cf) == n_algExt)
  479   {
  480     // poly
  481     return (number)ssiReadPoly_R(d,cf->extRing);
  482   }
  483   else WerrorS("coeffs not implemented in ssiReadNumber");
  484   return NULL;
  485 }
  486 
  487 number ssiReadBigInt(const ssiInfo *d)
  488 {
  489   number n=ssiReadNumber_CF(d,coeffs_BIGINT);
  490   if ((SR_HDL(n) & SR_INT)==0)
  491   {
  492     if (n->s!=3) Werror("invalid sub type in bigint:%d",n->s);
  493   }
  494   return n;
  495 }
  496 
  497 number ssiReadNumber(ssiInfo *d)
  498 {
  499   return ssiReadNumber_CF(d,d->r->cf);
  500 }
  501 
  502 ring ssiReadRing(const ssiInfo *d)
  503 {
  504 /* syntax is <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... <Q-ideal> */
  505   int ch;
  506   ch=s_readint(d->f_read);
  507   if (ch==-4)
  508     return NULL;
  509   int N=s_readint(d->f_read);
  510   char **names;
  511   coeffs cf=NULL;
  512   if (ch==-3)
  513   {
  514     char *cf_name=ssiReadString(d);
  515     cf=nFindCoeffByName(cf_name);
  516     if (cf==NULL)
  517     {
  518       Werror("cannot find cf:%s",cf_name);
  519       omFree(cf_name);
  520       return NULL;
  521     }
  522   }
  523   if (N!=0)
  524   {
  525     names=(char**)omAlloc(N*sizeof(char*));
  526     for(int i=0;i<N;i++)
  527     {
  528       names[i]=ssiReadString(d);
  529     }
  530   }
  531   // read the orderings:
  532   int num_ord; // number of orderings
  533   num_ord=s_readint(d->f_read);
  534   rRingOrder_t *ord=(rRingOrder_t *)omAlloc0((num_ord+1)*sizeof(rRingOrder_t));
  535   int *block0=(int *)omAlloc0((num_ord+1)*sizeof(int));
  536   int *block1=(int *)omAlloc0((num_ord+1)*sizeof(int));
  537   int **wvhdl=(int**)omAlloc0((num_ord+1)*sizeof(int*));
  538   for(int i=0;i<num_ord;i++)
  539   {
  540     ord[i]=(rRingOrder_t)s_readint(d->f_read);
  541     block0[i]=s_readint(d->f_read);
  542     block1[i]=s_readint(d->f_read);
  543     switch(ord[i])
  544     {
  545       case ringorder_a:
  546       case ringorder_wp:
  547       case ringorder_Wp:
  548       case ringorder_ws:
  549       case ringorder_Ws:
  550       case ringorder_aa:
  551       {
  552         wvhdl[i]=(int*)omAlloc((block1[i]-block0[i]+1)*sizeof(int));
  553         int ii;
  554         for(ii=block0[i];ii<=block1[i];ii++)
  555           wvhdl[i][ii-block0[i]]=s_readint(d->f_read);
  556       }
  557       break;
  558 
  559       case ringorder_a64:
  560       case ringorder_M:
  561       case ringorder_L:
  562       case ringorder_IS:
  563         Werror("ring oder not implemented for ssi:%d",ord[i]);
  564         break;
  565 
  566       default: break;
  567     }
  568   }
  569   if (N==0)
  570   {
  571     omFree(ord);
  572     omFree(block0);
  573     omFree(block1);
  574     omFree(wvhdl);
  575     return NULL;
  576   }
  577   else
  578   {
  579     ring r=NULL;
  580     if (ch>=0) /* Q, Z/p */
  581       r=rDefault(ch,N,names,num_ord,ord,block0,block1,wvhdl);
  582     else if (ch==-1) /* trans ext. */
  583     {
  584       TransExtInfo T;
  585       T.r=ssiReadRing(d);
  586       if (T.r==NULL) return NULL;
  587       cf=nInitChar(n_transExt,&T);
  588       r=rDefault(cf,N,names,num_ord,ord,block0,block1,wvhdl);
  589     }
  590     else if (ch==-2) /* alg ext. */
  591     {
  592       TransExtInfo T;
  593       T.r=ssiReadRing(d); /* includes qideal */
  594       if (T.r==NULL) return NULL;
  595       cf=nInitChar(n_algExt,&T);
  596       r=rDefault(cf,N,names,num_ord,ord,block0,block1,wvhdl);
  597     }
  598     else if (ch==-3)
  599     {
  600       r=rDefault(cf,N,names,num_ord,ord,block0,block1,wvhdl);
  601     }
  602     else
  603     {
  604       Werror("ssi: read unknown coeffs type (%d)",ch);
  605       for(int i=0;i<N;i++)
  606       {
  607         omFree(names[i]);
  608       }
  609       omFreeSize(names,N*sizeof(char*));
  610       return NULL;
  611     }
  612     ideal q=ssiReadIdeal_R(d,r);
  613     if (IDELEMS(q)==0) omFreeBin(q,sip_sideal_bin);
  614     else r->qideal=q;
  615     for(int i=0;i<N;i++)
  616     {
  617       omFree(names[i]);
  618     }
  619     omFreeSize(names,N*sizeof(char*));
  620     rIncRefCnt(r);
  621     // check if such ring already exist as ssiRing*
  622     char name[20];
  623     int nr=0;
  624     idhdl h=NULL;
  625     loop
  626     {
  627       sprintf(name,"ssiRing%d",nr); nr++;
  628       h=IDROOT->get(name, 0);
  629       if (h==NULL)
  630       {
  631         break;
  632       }
  633       else if ((IDTYP(h)==RING_CMD)
  634       && (r!=IDRING(h))
  635       && (rEqual(r,IDRING(h),1)))
  636       {
  637     rDelete(r);
  638         r=rIncRefCnt(IDRING(h));
  639         break;
  640       }
  641     }
  642     return r;
  643   }
  644 }
  645 
  646 poly ssiReadPoly_R(const ssiInfo *d, const ring r)
  647 {
  648 // < # of terms> < term1> < .....
  649   int n,i,l;
  650   n=ssiReadInt(d->f_read); // # of terms
  651   //Print("poly: terms:%d\n",n);
  652   poly p;
  653   poly ret=NULL;
  654   poly prev=NULL;
  655   for(l=0;l<n;l++) // read n terms
  656   {
  657 // coef,comp.exp1,..exp N
  658     p=p_Init(r,r->PolyBin);
  659     pSetCoeff0(p,ssiReadNumber_CF(d,r->cf));
  660     int D;
  661     D=s_readint(d->f_read);
  662     p_SetComp(p,D,r);
  663     for(i=1;i<=rVar(r);i++)
  664     {
  665       D=s_readint(d->f_read);
  666       p_SetExp(p,i,D,r);
  667     }
  668     p_Setm(p,r);
  669     p_Test(p,r);
  670     if (ret==NULL) ret=p;
  671     else           pNext(prev)=p;
  672     prev=p;
  673  }
  674  return ret;
  675 }
  676 
  677 poly ssiReadPoly(ssiInfo *d)
  678 {
  679   return ssiReadPoly_R(d,d->r);
  680 }
  681 
  682 ideal ssiReadIdeal_R(const ssiInfo *d,const ring r)
  683 {
  684 // < # of terms> < term1> < .....
  685   int n,i;
  686   ideal I;
  687   n=s_readint(d->f_read);
  688   I=idInit(n,1); // will be fixed later for module/smatrix
  689   for(i=0;i<IDELEMS(I);i++) // read n terms
  690   {
  691     I->m [i]=ssiReadPoly_R(d,r);
  692   }
  693   return I;
  694 }
  695 
  696 ideal ssiReadIdeal(ssiInfo *d)
  697 {
  698   return ssiReadIdeal_R(d,d->r);
  699 }
  700 
  701 matrix ssiReadMatrix(ssiInfo *d)
  702 {
  703   int n,m;
  704   m=s_readint(d->f_read);
  705   n=s_readint(d->f_read);
  706   matrix M=mpNew(m,n);
  707   poly p;
  708   for(int i=1;i<=MATROWS(M);i++)
  709     for(int j=1;j<=MATCOLS(M);j++)
  710     {
  711       p=ssiReadPoly(d);
  712       MATELEM(M,i,j)=p;
  713     }
  714   return M;
  715 }
  716 
  717 command ssiReadCommand(si_link l)
  718 {
  719   ssiInfo *d=(ssiInfo*)l->data;
  720   // syntax: <num ops> <operation> <op1> <op2> ....
  721   command D=(command)omAlloc0(sizeof(*D));
  722   int argc,op;
  723   argc=s_readint(d->f_read);
  724   op=s_readint(d->f_read);
  725   D->argc=argc; D->op=op;
  726   leftv v;
  727   if (argc >0)
  728   {
  729     v=ssiRead1(l);
  730     memcpy(&(D->arg1),v,sizeof(*v));
  731     omFreeBin(v,sleftv_bin);
  732   }
  733   if (argc <4)
  734   {
  735     if (D->argc >1)
  736     {
  737       v=ssiRead1(l);
  738       memcpy(&(D->arg2),v,sizeof(*v));
  739       omFreeBin(v,sleftv_bin);
  740     }
  741     if (D->argc >2)
  742     {
  743       v=ssiRead1(l);
  744       memcpy(&(D->arg3),v,sizeof(*v));
  745       omFreeBin(v,sleftv_bin);
  746     }
  747   }
  748   else
  749   {
  750     leftv prev=&(D->arg1);
  751     argc--;
  752     while(argc >0)
  753     {
  754       v=ssiRead1(l);
  755       prev->next=v;
  756       prev=v;
  757       argc--;
  758     }
  759   }
  760   return D;
  761 }
  762 
  763 procinfov ssiReadProc(const ssiInfo *d)
  764 {
  765   char *s=ssiReadString(d);
  766   procinfov p=(procinfov)omAlloc0Bin(procinfo_bin);
  767   p->language=LANG_SINGULAR;
  768   p->libname=omStrDup("");
  769   p->procname=omStrDup("");
  770   p->data.s.body=s;
  771   return p;
  772 }
  773 lists ssiReadList(si_link l)
  774 {
  775   ssiInfo *d=(ssiInfo*)l->data;
  776   int nr;
  777   nr=s_readint(d->f_read);
  778   lists L=(lists)omAlloc0Bin(slists_bin);
  779   L->Init(nr);
  780 
  781   int i;
  782   leftv v;
  783   for(i=0;i<=L->nr;i++)
  784   {
  785     v=ssiRead1(l);
  786     memcpy(&(L->m[i]),v,sizeof(*v));
  787     omFreeBin(v,sleftv_bin);
  788   }
  789   return L;
  790 }
  791 intvec* ssiReadIntvec(const ssiInfo *d)
  792 {
  793   int nr;
  794   nr=s_readint(d->f_read);
  795   intvec *v=new intvec(nr);
  796   for(int i=0;i<nr;i++)
  797   {
  798     (*v)[i]=s_readint(d->f_read);
  799   }
  800   return v;
  801 }
  802 intvec* ssiReadIntmat(const ssiInfo *d)
  803 {
  804   int r,c;
  805   r=s_readint(d->f_read);
  806   c=s_readint(d->f_read);
  807   intvec *v=new intvec(r,c,0);
  808   for(int i=0;i<r*c;i++)
  809   {
  810     (*v)[i]=s_readint(d->f_read);
  811   }
  812   return v;
  813 }
  814 bigintmat* ssiReadBigintmat(const ssiInfo *d)
  815 {
  816   int r,c;
  817   r=s_readint(d->f_read);
  818   c=s_readint(d->f_read);
  819   bigintmat *v=new bigintmat(r,c,coeffs_BIGINT);
  820   for(int i=0;i<r*c;i++)
  821   {
  822     (*v)[i]=ssiReadBigInt(d);
  823   }
  824   return v;
  825 }
  826 
  827 void ssiReadBlackbox(leftv res, si_link l)
  828 {
  829   ssiInfo *d=(ssiInfo*)l->data;
  830   int throwaway=s_readint(d->f_read);
  831   char *name=ssiReadString(d);
  832   int tok;
  833   blackboxIsCmd(name,tok);
  834   if (tok>MAX_TOK)
  835   {
  836     ring save_ring=currRing;
  837     idhdl save_hdl=currRingHdl;
  838     blackbox *b=getBlackboxStuff(tok);
  839     res->rtyp=tok;
  840     b->blackbox_deserialize(&b,&(res->data),l);
  841     if (save_ring!=currRing)
  842     {
  843       rChangeCurrRing(save_ring);
  844       if (save_hdl!=NULL) rSetHdl(save_hdl);
  845       else currRingHdl=NULL;
  846     }
  847   }
  848   else
  849   {
  850     Werror("blackbox %s not found",name);
  851   }
  852   omFree(name);
  853 }
  854 
  855 void ssiReadAttrib(leftv res, si_link l)
  856 {
  857   ssiInfo *d=(ssiInfo*)l->data;
  858   BITSET fl=(BITSET)s_readint(d->f_read);
  859   int nr_of_attr=s_readint(d->f_read);
  860   if (nr_of_attr>0)
  861   {
  862     for(int i=1;i<nr_of_attr;i++)
  863     {
  864     }
  865   }
  866   leftv tmp=ssiRead1(l);
  867   memcpy(res,tmp,sizeof(sleftv));
  868   memset(tmp,0,sizeof(sleftv));
  869   omFreeBin(tmp,sleftv_bin);
  870   if (nr_of_attr>0)
  871   {
  872   }
  873   res->flag=fl;
  874 }
  875 void ssiReadRingProperties(si_link l)
  876 {
  877   ssiInfo *d=(ssiInfo*)l->data;
  878   int what=s_readint(d->f_read);
  879   switch(what)
  880   {
  881     case 0: // bitmask
  882     {
  883       int lb=s_readint(d->f_read);
  884       unsigned long bm=~0L;
  885       bm=bm<<lb;
  886       bm=~bm;
  887       rUnComplete(d->r);
  888       d->r->bitmask=bm;
  889       rComplete(d->r);
  890       break;
  891     }
  892     case 1: // LPRing
  893     {
  894       int lb=s_readint(d->f_read);
  895       int isLPring=s_readint(d->f_read);
  896       unsigned long bm=~0L;
  897       bm=bm<<lb;
  898       bm=~bm;
  899       rUnComplete(d->r);
  900       d->r->bitmask=bm;
  901       d->r->isLPring=isLPring;
  902       rComplete(d->r);
  903       break;
  904     }
  905     case 2: // Plural rings
  906     {
  907       matrix C=ssiReadMatrix(d);
  908       matrix D=ssiReadMatrix(d);
  909       nc_CallPlural(C,D,NULL,NULL,d->r,true,true,false,d->r,false);
  910       break;
  911     }
  912   }
  913 }
  914 //**************************************************************************/
  915 
  916 BOOLEAN ssiOpen(si_link l, short flag, leftv u)
  917 {
  918   if (l!=NULL)
  919   {
  920     const char *mode;
  921     ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
  922     if (flag & SI_LINK_OPEN)
  923     {
  924       if (l->mode[0] != '\0' && (strcmp(l->mode, "r") == 0))
  925         flag = SI_LINK_READ;
  926       else flag = SI_LINK_WRITE;
  927     }
  928 
  929     if (flag == SI_LINK_READ) mode = "r";
  930     else if (strcmp(l->mode, "w") == 0) mode = "w";
  931     else if (strcmp(l->mode, "fork") == 0) mode = "fork";
  932     else if (strcmp(l->mode, "tcp") == 0) mode = "tcp";
  933     else if (strcmp(l->mode, "connect") == 0) mode = "connect";
  934     else mode = "a";
  935 
  936 
  937     SI_LINK_SET_OPEN_P(l, flag);
  938     if(l->data!=NULL) omFreeSize(l->data,sizeof(ssiInfo));
  939     l->data=d;
  940     omFree(l->mode);
  941     l->mode = omStrDup(mode);
  942 
  943     if (l->name[0] == '\0')
  944     {
  945       if (strcmp(mode,"fork")==0)
  946       {
  947         link_list n=(link_list)omAlloc(sizeof(link_struct));
  948         n->u=u;
  949         n->l=l;
  950         n->next=(void *)ssiToBeClosed;
  951         ssiToBeClosed=n;
  952 
  953         int pc[2];
  954         int cp[2];
  955         pipe(pc);
  956         pipe(cp);
  957         pid_t pid = fork();
  958         if (pid == -1 && errno == EAGAIN)   // RLIMIT_NPROC too low?
  959         {
  960           raise_rlimit_nproc();
  961           pid = fork();
  962         }
  963         if (pid == -1)
  964         {
  965           WerrorS("could not fork");
  966         }
  967         if (pid==0) /*fork: child*/
  968         {
  969           /* block SIGINT */
  970           sigset_t sigint;
  971           sigemptyset(&sigint);
  972           sigaddset(&sigint, SIGINT);
  973           sigprocmask(SIG_BLOCK, &sigint, NULL);
  974           /* set #cpu to 1 for the child:*/
  975           feSetOptValue(FE_OPT_CPUS,1);
  976 
  977           link_list hh=(link_list)ssiToBeClosed->next;
  978           /* we know: l is the first entry in ssiToBeClosed-list */
  979           while(hh!=NULL)
  980           {
  981             SI_LINK_SET_CLOSE_P(hh->l);
  982             ssiInfo *dd=(ssiInfo*)hh->l->data;
  983             s_close(dd->f_read);
  984             fclose(dd->f_write);
  985             if (dd->r!=NULL) rKill(dd->r);
  986             omFreeSize((ADDRESS)dd,(sizeof *dd));
  987             hh->l->data=NULL;
  988             link_list nn=(link_list)hh->next;
  989             omFree(hh);
  990             hh=nn;
  991           }
  992           ssiToBeClosed->next=NULL;
  993 #ifdef HAVE_SIMPLEIPC
  994           memset(sem_acquired, 0, SIPC_MAX_SEMAPHORES*sizeof(sem_acquired[0]));
  995 #endif   // HAVE_SIMPLEIPC
  996           si_close(pc[1]); si_close(cp[0]);
  997           d->f_write=fdopen(cp[1],"w");
  998           d->f_read=s_open(pc[0]);
  999           d->fd_read=pc[0];
 1000           d->fd_write=cp[1];
 1001           //d->r=currRing;
 1002           //if (d->r!=NULL) d->r->ref++;
 1003           l->data=d;
 1004           omFree(l->mode);
 1005           l->mode = omStrDup(mode);
 1006           singular_in_batchmode=TRUE;
 1007           SI_LINK_SET_RW_OPEN_P(l);
 1008           //myynest=0;
 1009           fe_fgets_stdin=fe_fgets_dummy;
 1010           if ((u!=NULL)&&(u->rtyp==IDHDL))
 1011           {
 1012             idhdl h=(idhdl)u->data;
 1013             h->lev=0;
 1014           }
 1015           loop
 1016           {
 1017             if (!SI_LINK_OPEN_P(l)) m2_end(0);
 1018             if(d->f_read->is_eof) m2_end(0);
 1019             leftv h=ssiRead1(l); /*contains an exit.... */
 1020             if (feErrors != NULL && *feErrors != '\0')
 1021             {
 1022               // handle errors:
 1023               PrintS(feErrors); /* currently quite simple */
 1024               *feErrors = '\0';
 1025             }
 1026             ssiWrite(l,h);
 1027             h->CleanUp();
 1028             omFreeBin(h, sleftv_bin);
 1029           }
 1030           /* never reached*/
 1031         }
 1032         else if (pid>0) /*fork: parent*/
 1033         {
 1034           d->pid=pid;
 1035           si_close(pc[0]); si_close(cp[1]);
 1036           d->f_write=fdopen(pc[1],"w");
 1037           d->f_read=s_open(cp[0]);
 1038           d->fd_read=cp[0];
 1039           d->fd_write=pc[1];
 1040           SI_LINK_SET_RW_OPEN_P(l);
 1041           d->send_quit_at_exit=1;
 1042           //d->r=currRing;
 1043           //if (d->r!=NULL) d->r->ref++;
 1044         }
 1045         else
 1046         {
 1047           Werror("fork failed (%d)",errno);
 1048           l->data=NULL;
 1049           omFree(d);
 1050           return TRUE;
 1051         }
 1052       }
 1053       // ---------------------------------------------------------------------
 1054       else if (strcmp(mode,"tcp")==0)
 1055       {
 1056         int sockfd, newsockfd, portno, clilen;
 1057         struct sockaddr_in serv_addr, cli_addr;
 1058         sockfd = socket(AF_INET, SOCK_STREAM, 0);
 1059         if(sockfd < 0)
 1060         {
 1061           WerrorS("ERROR opening socket");
 1062           l->data=NULL;
 1063           SI_LINK_CLOSE_P(l);
 1064           omFree(d);
 1065           return TRUE;
 1066         }
 1067         memset((char *) &serv_addr,0, sizeof(serv_addr));
 1068         portno = 1025;
 1069         serv_addr.sin_family = AF_INET;
 1070         serv_addr.sin_addr.s_addr = INADDR_ANY;
 1071         do
 1072         {
 1073           portno++;
 1074           serv_addr.sin_port = htons(portno);
 1075           if(portno > 50000)
 1076           {
 1077             WerrorS("ERROR on binding (no free port available?)");
 1078             l->data=NULL;
 1079             SI_LINK_CLOSE_P(l);
 1080             omFree(d);
 1081             return TRUE;
 1082           }
 1083         }
 1084         while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
 1085         Print("waiting on port %d\n", portno);mflush();
 1086         listen(sockfd,1);
 1087         newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
 1088         if(newsockfd < 0)
 1089         {
 1090           WerrorS("ERROR on accept");
 1091           l->data=NULL;
 1092           SI_LINK_CLOSE_P(l);
 1093           omFree(d);
 1094           return TRUE;
 1095         }
 1096         PrintS("client accepted\n");
 1097         d->fd_read = newsockfd;
 1098         d->fd_write = newsockfd;
 1099         d->f_read = s_open(newsockfd);
 1100         d->f_write = fdopen(newsockfd, "w");
 1101         SI_LINK_SET_RW_OPEN_P(l);
 1102         si_close(sockfd);
 1103       }
 1104       // no ssi-Link on stdin or stdout
 1105       else
 1106       {
 1107         Werror("invalid mode >>%s<< for ssi",mode);
 1108         l->data=NULL;
 1109         SI_LINK_CLOSE_P(l);
 1110         omFree(d);
 1111         return TRUE;
 1112       }
 1113     }
 1114     // =========================================================================
 1115     else /*l->name=NULL*/
 1116     {
 1117       // tcp mode
 1118       if(strcmp(mode,"tcp")==0)
 1119       {
 1120         int sockfd, newsockfd, portno, clilen;
 1121         struct sockaddr_in serv_addr, cli_addr;
 1122         sockfd = socket(AF_INET, SOCK_STREAM, 0);
 1123         if(sockfd < 0)
 1124         {
 1125           WerrorS("ERROR opening socket");
 1126           l->data=NULL;
 1127           SI_LINK_CLOSE_P(l);
 1128           omFree(d);
 1129           return TRUE;
 1130         }
 1131         memset((char *) &serv_addr,0, sizeof(serv_addr));
 1132         portno = 1025;
 1133         serv_addr.sin_family = AF_INET;
 1134         serv_addr.sin_addr.s_addr = INADDR_ANY;
 1135         do
 1136         {
 1137           portno++;
 1138           serv_addr.sin_port = htons(portno);
 1139           if(portno > 50000)
 1140           {
 1141             WerrorS("ERROR on binding (no free port available?)");
 1142             l->data=NULL;
 1143             SI_LINK_CLOSE_P(l);
 1144             return TRUE;
 1145           }
 1146         }
 1147         while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
 1148         //Print("waiting on port %d\n", portno);mflush();
 1149         listen(sockfd,1);
 1150         char* cli_host = (char*)omAlloc(256);
 1151         char* path = (char*)omAlloc(1024);
 1152         int r = si_sscanf(l->name,"%255[^:]:%s",cli_host,path);
 1153         if(r == 0)
 1154         {
 1155           WerrorS("ERROR: no host specified");
 1156           l->data=NULL;
 1157           SI_LINK_CLOSE_P(l);
 1158           omFree(d);
 1159           omFree(path);
 1160           omFree(cli_host);
 1161           return TRUE;
 1162         }
 1163         else if(r == 1)
 1164         {
 1165           WarnS("program not specified, using /usr/local/bin/Singular");
 1166           Warn("in line >>%s<<",my_yylinebuf);
 1167           strcpy(path,"/usr/local/bin/Singular");
 1168         }
 1169         char* ssh_command = (char*)omAlloc(256);
 1170         char* ser_host = (char*)omAlloc(64);
 1171         gethostname(ser_host,64);
 1172         if (strcmp(cli_host,"localhost")==0) /*avoid "ssh localhost" as key may change*/
 1173           sprintf(ssh_command,"%s -q --batch --link=ssi --MPhost=%s --MPport=%d &",path,ser_host,portno);
 1174         else
 1175           sprintf(ssh_command,"ssh %s %s -q --batch --link=ssi --MPhost=%s --MPport=%d &",cli_host,path,ser_host,portno);
 1176         //Print("client on %s started:%s\n",cli_host,path);
 1177         omFree(path);
 1178         omFree(cli_host);
 1179         if (TEST_OPT_PROT) { Print("running >>%s<<\n",ssh_command); }
 1180         system(ssh_command);
 1181         omFree(ssh_command);
 1182         omFree(ser_host);
 1183         clilen = sizeof(cli_addr);
 1184         newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
 1185         if(newsockfd < 0)
 1186         {
 1187           WerrorS("ERROR on accept");
 1188           l->data=NULL;
 1189           SI_LINK_CLOSE_P(l);
 1190           omFree(d);
 1191           return TRUE;
 1192         }
 1193         //PrintS("client accepted\n");
 1194         d->fd_read = newsockfd;
 1195         d->fd_write = newsockfd;
 1196         d->f_read = s_open(newsockfd);
 1197         d->f_write = fdopen(newsockfd, "w");
 1198         si_close(sockfd);
 1199         SI_LINK_SET_RW_OPEN_P(l);
 1200         d->send_quit_at_exit=1;
 1201         link_list newlink=(link_list)omAlloc(sizeof(link_struct));
 1202         newlink->u=u;
 1203         newlink->l=l;
 1204         newlink->next=(void *)ssiToBeClosed;
 1205         ssiToBeClosed=newlink;
 1206         fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2);
 1207       }
 1208       // ----------------------------------------------------------------------
 1209       else if(strcmp(mode,"connect")==0)
 1210       {
 1211         char* host = (char*)omAlloc(256);
 1212         int sockfd, portno;
 1213         struct sockaddr_in serv_addr;
 1214         struct hostent *server;
 1215 
 1216         si_sscanf(l->name,"%255[^:]:%d",host,&portno);
 1217         //Print("connect to host %s, port %d\n",host,portno);mflush();
 1218         if (portno!=0)
 1219         {
 1220           sockfd = socket(AF_INET, SOCK_STREAM, 0);
 1221           if (sockfd < 0)
 1222           {
 1223             WerrorS("ERROR opening socket");
 1224             SI_LINK_CLOSE_P(l);
 1225             return TRUE;
 1226           }
 1227           server = gethostbyname(host);
 1228           if (server == NULL)
 1229           {
 1230             WerrorS("ERROR, no such host");
 1231             SI_LINK_CLOSE_P(l);
 1232             return TRUE;
 1233           }
 1234           memset((char *) &serv_addr, 0, sizeof(serv_addr));
 1235           serv_addr.sin_family = AF_INET;
 1236           memcpy((char *)&serv_addr.sin_addr.s_addr,
 1237                 (char *)server->h_addr,
 1238                 server->h_length);
 1239           serv_addr.sin_port = htons(portno);
 1240           if (si_connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
 1241           {
 1242             Werror("ERROR connecting(errno=%d)",errno);
 1243             SI_LINK_CLOSE_P(l);
 1244             return TRUE;
 1245           }
 1246           //PrintS("connected\n");mflush();
 1247           d->f_read=s_open(sockfd);
 1248           d->fd_read=sockfd;
 1249           d->f_write=fdopen(sockfd,"w");
 1250           d->fd_write=sockfd;
 1251           SI_LINK_SET_RW_OPEN_P(l);
 1252           omFree(host);
 1253         }
 1254         else
 1255         {
 1256           l->data=NULL;
 1257           SI_LINK_CLOSE_P(l);
 1258           omFree(d);
 1259           return TRUE;
 1260         }
 1261       }
 1262       // ======================================================================
 1263       else
 1264       {
 1265         // normal link to a file
 1266         FILE *outfile;
 1267         char *filename=l->name;
 1268 
 1269         if(filename[0]=='>')
 1270         {
 1271           if (filename[1]=='>')
 1272           {
 1273             filename+=2;
 1274             mode = "a";
 1275           }
 1276           else
 1277           {
 1278             filename++;
 1279             mode="w";
 1280           }
 1281         }
 1282         outfile=myfopen(filename,mode);
 1283         if (outfile!=NULL)
 1284         {
 1285           if (strcmp(l->mode,"r")==0)
 1286           {
 1287             fclose(outfile);
 1288             d->f_read=s_open_by_name(filename);
 1289           }
 1290           else
 1291           {
 1292             d->f_write = outfile;
 1293             fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2);
 1294           }
 1295         }
 1296         else
 1297         {
 1298           omFree(d);
 1299           l->data=NULL;
 1300           SI_LINK_CLOSE_P(l);
 1301           return TRUE;
 1302         }
 1303       }
 1304     }
 1305   }
 1306 
 1307   return FALSE;
 1308 }
 1309 
 1310 //**************************************************************************/
 1311 BOOLEAN ssiPrepClose(si_link l)
 1312 {
 1313   if (l!=NULL)
 1314   {
 1315     SI_LINK_SET_CLOSE_P(l);
 1316     ssiInfo *d = (ssiInfo *)l->data;
 1317     if (d!=NULL)
 1318     {
 1319       if (d->send_quit_at_exit)
 1320       {
 1321         fputs("99\n",d->f_write);
 1322         fflush(d->f_write);
 1323       }
 1324       d->quit_sent=1;
 1325     }
 1326   }
 1327   return FALSE;
 1328 }
 1329 
 1330 BOOLEAN ssiClose(si_link l)
 1331 {
 1332   if (l!=NULL)
 1333   {
 1334     SI_LINK_SET_CLOSE_P(l);
 1335     ssiInfo *d = (ssiInfo *)l->data;
 1336     if (d!=NULL)
 1337     {
 1338       // send quit signal
 1339       if ((d->send_quit_at_exit)
 1340       && (d->quit_sent==0))
 1341       {
 1342         fputs("99\n",d->f_write);
 1343         fflush(d->f_write);
 1344       }
 1345       // clean ring
 1346       if (d->r!=NULL) rKill(d->r);
 1347       // did the child to stop ?
 1348       si_waitpid(d->pid,NULL,WNOHANG);
 1349       if ((d->pid!=0)
 1350       && (kill(d->pid,0)==0)) // child is still running
 1351       {
 1352         struct timespec t;
 1353         t.tv_sec=0;
 1354         t.tv_nsec=100000000; // <=100 ms
 1355         struct timespec rem;
 1356         int r;
 1357         loop
 1358         {
 1359           // wait till signal or time rem:
 1360           r = nanosleep(&t, &rem);
 1361           t = rem;
 1362           // child finished:
 1363           if (si_waitpid(d->pid,NULL,WNOHANG) != 0) break;
 1364           // other signal, waited s>= 100 ms:
 1365           if ((r==0) || (errno != EINTR)) break;
 1366         }
 1367         if (kill(d->pid,0) == 0) // pid still exists
 1368         {
 1369           kill(d->pid,15);
 1370           t.tv_sec=5; // <=5s
 1371           t.tv_nsec=0;
 1372           loop
 1373           {
 1374             // wait till signal or time rem:
 1375             r = nanosleep(&t, &rem);
 1376             t = rem;
 1377             // child finished:
 1378             if (si_waitpid(d->pid,NULL,WNOHANG) != 0) break;
 1379             // other signal, waited s>=  5 s:
 1380             if ((r==0) || (errno != EINTR)) break;
 1381           }
 1382           if (kill(d->pid,0) == 0)
 1383           {
 1384             kill(d->pid,9); // just to be sure
 1385             si_waitpid(d->pid,NULL,0);
 1386           }
 1387         }
 1388       }
 1389       if (d->f_read!=NULL) { s_close(d->f_read);d->f_read=NULL;}
 1390       if (d->f_write!=NULL) { fclose(d->f_write); d->f_write=NULL; }
 1391       if ((strcmp(l->mode,"tcp")==0)
 1392       || (strcmp(l->mode,"fork")==0))
 1393       {
 1394         link_list hh=ssiToBeClosed;
 1395         if (hh!=NULL)
 1396         {
 1397           if (hh->l==l)
 1398           {
 1399              ssiToBeClosed=(link_list)hh->next;
 1400              omFreeSize(hh,sizeof(link_struct));
 1401           }
 1402           else while(hh->next!=NULL)
 1403           {
 1404             link_list hhh=(link_list)hh->next;
 1405             if (hhh->l==l)
 1406             {
 1407               hh->next=hhh->next;
 1408               omFreeSize(hhh,sizeof(link_struct));
 1409               break;
 1410             }
 1411             else
 1412               hh=(link_list)hh->next;
 1413           }
 1414         }
 1415       }
 1416       omFreeSize((ADDRESS)d,(sizeof *d));
 1417     }
 1418     l->data=NULL;
 1419   }
 1420   return FALSE;
 1421 }
 1422 
 1423 //**************************************************************************/
 1424 leftv ssiRead1(si_link l)
 1425 {
 1426   ssiInfo *d = (ssiInfo *)l->data;
 1427   leftv res=(leftv)omAlloc0Bin(sleftv_bin);
 1428   int t=0;
 1429   t=s_readint(d->f_read);
 1430   //Print("got type %d\n",t);
 1431   switch(t)
 1432   {
 1433     case 1:res->rtyp=INT_CMD;
 1434            res->data=(char *)(long)ssiReadInt(d->f_read);
 1435            break;
 1436     case 2:res->rtyp=STRING_CMD;
 1437            res->data=(char *)ssiReadString(d);
 1438            break;
 1439     case 3:res->rtyp=NUMBER_CMD;
 1440            if (d->r==NULL) goto no_ring;
 1441            ssiCheckCurrRing(d->r);
 1442            res->data=(char *)ssiReadNumber(d);
 1443            break;
 1444     case 4:res->rtyp=BIGINT_CMD;
 1445            res->data=(char *)ssiReadBigInt(d);
 1446            break;
 1447     case 15:
 1448     case 5:{
 1449              d->r=ssiReadRing(d);
 1450              if (errorreported) return NULL;
 1451              res->data=(char*)d->r;
 1452              if (d->r!=NULL) rIncRefCnt(d->r);
 1453              res->rtyp=RING_CMD;
 1454              if (t==15) // setring
 1455              {
 1456                if(ssiSetCurrRing(d->r)) { d->r=currRing; }
 1457                omFreeBin(res,sleftv_bin);
 1458                return ssiRead1(l);
 1459              }
 1460            }
 1461            break;
 1462     case 6:res->rtyp=POLY_CMD;
 1463            if (d->r==NULL) goto no_ring;
 1464            ssiCheckCurrRing(d->r);
 1465            res->data=(char*)ssiReadPoly(d);
 1466            break;
 1467     case 7:res->rtyp=IDEAL_CMD;
 1468            if (d->r==NULL) goto no_ring;
 1469            ssiCheckCurrRing(d->r);
 1470            res->data=(char*)ssiReadIdeal(d);
 1471            break;
 1472     case 8:res->rtyp=MATRIX_CMD;
 1473            if (d->r==NULL) goto no_ring;
 1474            ssiCheckCurrRing(d->r);
 1475            res->data=(char*)ssiReadMatrix(d);
 1476            break;
 1477     case 9:res->rtyp=VECTOR_CMD;
 1478            if (d->r==NULL) goto no_ring;
 1479            ssiCheckCurrRing(d->r);
 1480            res->data=(char*)ssiReadPoly(d);
 1481            break;
 1482     case 10:
 1483     case 22:if (t==22) res->rtyp=SMATRIX_CMD;
 1484            else        res->rtyp=MODUL_CMD;
 1485            if (d->r==NULL) goto no_ring;
 1486            ssiCheckCurrRing(d->r);
 1487            {
 1488              int rk=s_readint(d->f_read);
 1489              ideal M=ssiReadIdeal(d);
 1490              M->rank=rk;
 1491              res->data=(char*)M;
 1492            }
 1493            break;
 1494     case 11:
 1495            {
 1496              res->rtyp=COMMAND;
 1497              res->data=ssiReadCommand(l);
 1498              int nok=res->Eval();
 1499              if (nok) WerrorS("error in eval");
 1500              break;
 1501            }
 1502     case 12: /*DEF_CMD*/
 1503            {
 1504              res->rtyp=0;
 1505              res->name=(char *)ssiReadString(d);
 1506              int nok=res->Eval();
 1507              if (nok) WerrorS("error in name lookup");
 1508              break;
 1509            }
 1510     case 13: res->rtyp=PROC_CMD;
 1511              res->data=ssiReadProc(d);
 1512              break;
 1513     case 14: res->rtyp=LIST_CMD;
 1514              res->data=ssiReadList(l);
 1515              break;
 1516     case 16: res->rtyp=NONE; res->data=NULL;
 1517              break;
 1518     case 17: res->rtyp=INTVEC_CMD;
 1519              res->data=ssiReadIntvec(d);
 1520              break;
 1521     case 18: res->rtyp=INTMAT_CMD;
 1522              res->data=ssiReadIntmat(d);
 1523              break;
 1524     case 19: res->rtyp=BIGINTMAT_CMD;
 1525              res->data=ssiReadBigintmat(d);
 1526              break;
 1527     case 20: ssiReadBlackbox(res,l);
 1528              break;
 1529     case 21: ssiReadAttrib(res,l);
 1530              break;
 1531     case 23: ssiReadRingProperties(l);
 1532              return ssiRead1(l);
 1533              break;
 1534     // ------------
 1535     case 98: // version
 1536              {
 1537                 int n98_v,n98_m;
 1538                 BITSET n98_o1,n98_o2;
 1539                 n98_v=s_readint(d->f_read);
 1540                 n98_m=s_readint(d->f_read);
 1541                 n98_o1=s_readint(d->f_read);
 1542                 n98_o2=s_readint(d->f_read);
 1543                 if ((n98_v!=SSI_VERSION) ||(n98_m!=MAX_TOK))
 1544                 {
 1545                   Print("incompatible versions of ssi: %d/%d vs %d/%d\n",
 1546                                   SSI_VERSION,MAX_TOK,n98_v,n98_m);
 1547                 }
 1548                 #ifndef SING_NDEBUG
 1549                 if (TEST_OPT_DEBUG)
 1550                   Print("// opening ssi-%d, MAX_TOK=%d\n",n98_v,n98_m);
 1551                 #endif
 1552                 si_opt_1=n98_o1;
 1553                 si_opt_2=n98_o2;
 1554                 omFreeBin(res,sleftv_bin);
 1555                 return ssiRead1(l);
 1556              }
 1557     case 99: omFreeBin(res,sleftv_bin); ssiClose(l); m2_end(0);
 1558     case 0: if (s_iseof(d->f_read))
 1559             {
 1560               ssiClose(l);
 1561             }
 1562             res->rtyp=DEF_CMD;
 1563             break;
 1564     default: Werror("not implemented (t:%d)",t);
 1565              omFreeBin(res,sleftv_bin);
 1566              res=NULL;
 1567              break;
 1568   }
 1569   // if currRing is required for the result, but lost
 1570   // define "ssiRing%d" as currRing:
 1571   if ((d->r!=NULL)
 1572   && (currRing!=d->r)
 1573   && (res->RingDependend()))
 1574   {
 1575     if(ssiSetCurrRing(d->r)) { d->r=currRing; }
 1576   }
 1577   return res;
 1578 no_ring: WerrorS("no ring");
 1579   omFreeBin(res,sleftv_bin);
 1580   return NULL;
 1581 }
 1582 //**************************************************************************/
 1583 BOOLEAN ssiSetRing(si_link l, ring r, BOOLEAN send)
 1584 {
 1585   if(SI_LINK_W_OPEN_P(l)==0)
 1586      if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE;
 1587   ssiInfo *d = (ssiInfo *)l->data;
 1588   if (d->r!=r)
 1589   {
 1590     if (send)
 1591     {
 1592       fputs("15 ",d->f_write);
 1593       ssiWriteRing(d,r);
 1594     }
 1595     d->r=r;
 1596   }
 1597   if (currRing!=r) rChangeCurrRing(r);
 1598   return FALSE;
 1599 }
 1600 //**************************************************************************/
 1601 
 1602 BOOLEAN ssiWrite(si_link l, leftv data)
 1603 {
 1604   if(SI_LINK_W_OPEN_P(l)==0)
 1605      if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE;
 1606   ssiInfo *d = (ssiInfo *)l->data;
 1607   d->level++;
 1608   //FILE *fich=d->f;
 1609   while (data!=NULL)
 1610   {
 1611     int tt=data->Typ();
 1612     void *dd=data->Data();
 1613     attr *aa=data->Attribute();
 1614     if ((aa!=NULL) && ((*aa)!=NULL)) // n user attributes
 1615     {
 1616       attr a=*aa;
 1617       int n=0;
 1618       while(a!=NULL) { n++; a=a->next;}
 1619       fprintf(d->f_write,"21 %d %d ",data->flag,n);
 1620     }
 1621     else if (data->flag!=0) // only "flag" attributes
 1622     {
 1623       fprintf(d->f_write,"21 %d 0 ",data->flag);
 1624     }
 1625     if ((dd==NULL) && (data->name!=NULL) && (tt==0)) tt=DEF_CMD;
 1626       // return pure undefined names as def
 1627 
 1628     switch(tt /*data->Typ()*/)
 1629     {
 1630           case 0: /*error*/
 1631           case NONE/* nothing*/:fputs("16 ",d->f_write);
 1632                           break;
 1633           case STRING_CMD: fputs("2 ",d->f_write);
 1634                            ssiWriteString(d,(char *)dd);
 1635                            break;
 1636           case INT_CMD: fputs("1 ",d->f_write);
 1637                         ssiWriteInt(d,(int)(long)dd);
 1638                         break;
 1639           case BIGINT_CMD:fputs("4 ",d->f_write);
 1640                         ssiWriteBigInt(d,(number)dd);
 1641                         break;
 1642           case NUMBER_CMD:
 1643                           if (d->r!=currRing)
 1644                           {
 1645                             fputs("15 ",d->f_write);
 1646                             ssiWriteRing(d,currRing);
 1647                             if (d->level<=1) fputc('\n',d->f_write);
 1648                           }
 1649                           fputs("3 ",d->f_write);
 1650                           ssiWriteNumber(d,(number)dd);
 1651                         break;
 1652           case RING_CMD:fputs("5 ",d->f_write);
 1653                         ssiWriteRing(d,(ring)dd);
 1654                         break;
 1655           case BUCKET_CMD:
 1656                         {
 1657                           sBucket_pt b=(sBucket_pt)dd;
 1658                           if (d->r!=sBucketGetRing(b))
 1659                           {
 1660                             fputs("15 ",d->f_write);
 1661                             ssiWriteRing(d,sBucketGetRing(b));
 1662                             if (d->level<=1) fputc('\n',d->f_write);
 1663                           }
 1664                           fputs("6 ",d->f_write);
 1665                           ssiWritePoly(d,tt,sBucketPeek(b));
 1666                           break;
 1667                         }
 1668           case POLY_CMD:
 1669           case VECTOR_CMD:
 1670                         if (d->r!=currRing)
 1671                         {
 1672                           fputs("15 ",d->f_write);
 1673                           ssiWriteRing(d,currRing);
 1674                           if (d->level<=1) fputc('\n',d->f_write);
 1675                         }
 1676                         if(tt==POLY_CMD) fputs("6 ",d->f_write);
 1677                         else             fputs("9 ",d->f_write);
 1678                         ssiWritePoly(d,tt,(poly)dd);
 1679                         break;
 1680           case IDEAL_CMD:
 1681           case MODUL_CMD:
 1682           case MATRIX_CMD:
 1683           case SMATRIX_CMD:
 1684                         if (d->r!=currRing)
 1685                         {
 1686                           fputs("15 ",d->f_write);
 1687                           ssiWriteRing(d,currRing);
 1688                           if (d->level<=1) fputc('\n',d->f_write);
 1689                         }
 1690                         if(tt==IDEAL_CMD)       fputs("7 ",d->f_write);
 1691                         else if(tt==MATRIX_CMD) fputs("8 ",d->f_write);
 1692                         else if(tt==SMATRIX_CMD) fputs("22 ",d->f_write);
 1693                         else /* tt==MODUL_CMD*/
 1694                         {
 1695                           ideal M=(ideal)dd;
 1696                           fprintf(d->f_write,"10 %d ",(int)M->rank);
 1697                         }
 1698                         ssiWriteIdeal(d,tt,(ideal)dd);
 1699                         break;
 1700           case COMMAND:
 1701                    fputs("11 ",d->f_write);
 1702                    ssiWriteCommand(l,(command)dd);
 1703                    break;
 1704           case DEF_CMD: /* not evaluated stuff in quotes */
 1705                    fputs("12 ",d->f_write);
 1706                    ssiWriteString(d,data->Name());
 1707                    break;
 1708           case PROC_CMD:
 1709                    fputs("13 ",d->f_write);
 1710                    ssiWriteProc(d,(procinfov)dd);
 1711                    break;
 1712           case LIST_CMD:
 1713                    fputs("14 ",d->f_write);
 1714                    ssiWriteList(l,(lists)dd);
 1715                    break;
 1716           case INTVEC_CMD:
 1717                    fputs("17 ",d->f_write);
 1718                    ssiWriteIntvec(d,(intvec *)dd);
 1719                    break;
 1720           case INTMAT_CMD:
 1721                    fputs("18 ",d->f_write);
 1722                    ssiWriteIntmat(d,(intvec *)dd);
 1723                    break;
 1724           case BIGINTMAT_CMD:
 1725                    fputs("19 ",d->f_write);
 1726                    ssiWriteBigintmat(d,(bigintmat *)dd);
 1727                    break;
 1728           default:
 1729             if (tt>MAX_TOK)
 1730             {
 1731               blackbox *b=getBlackboxStuff(tt);
 1732               fputs("20 ",d->f_write);
 1733               b->blackbox_serialize(b,dd,l);
 1734             }
 1735             else
 1736             {
 1737               Werror("not implemented (t:%d, rtyp:%d)",tt, data->rtyp);
 1738               d->level=0;
 1739               return TRUE;
 1740             }
 1741             break;
 1742     }
 1743     if (d->level<=1) { fputc('\n',d->f_write); fflush(d->f_write); }
 1744     data=data->next;
 1745   }
 1746   d->level--;
 1747   return FALSE;
 1748 }
 1749 
 1750 BOOLEAN ssiGetDump(si_link l);
 1751 BOOLEAN ssiDump(si_link l);
 1752 
 1753 si_link_extension slInitSsiExtension(si_link_extension s)
 1754 {
 1755   s->Open=ssiOpen;
 1756   s->Close=ssiClose;
 1757   s->Kill=ssiClose;
 1758   s->Read=ssiRead1;
 1759   s->Read2=(slRead2Proc)NULL;
 1760   s->Write=ssiWrite;
 1761   s->Dump=ssiDump;
 1762   s->GetDump=ssiGetDump;
 1763 
 1764   s->Status=slStatusSsi;
 1765   s->SetRing=ssiSetRing;
 1766   s->type="ssi";
 1767   return s;
 1768 }
 1769 
 1770 const char* slStatusSsi(si_link l, const char* request)
 1771 {
 1772   ssiInfo *d=(ssiInfo*)l->data;
 1773   if (d==NULL) return "not open";
 1774   if (((strcmp(l->mode,"fork")==0)
 1775   ||(strcmp(l->mode,"tcp")==0)
 1776   ||(strcmp(l->mode,"connect")==0))
 1777   && (strcmp(request, "read") == 0))
 1778   {
 1779     fd_set  mask;
 1780     struct timeval wt;
 1781     if (s_isready(d->f_read)) return "ready";
 1782     loop
 1783     {
 1784       /* Don't block. Return socket status immediately. */
 1785       wt.tv_sec  = 0;
 1786       wt.tv_usec = 0;
 1787 
 1788       FD_ZERO(&mask);
 1789       FD_SET(d->fd_read, &mask);
 1790       //Print("test fd %d\n",d->fd_read);
 1791     /* check with select: chars waiting: no -> not ready */
 1792       switch (si_select(d->fd_read+1, &mask, NULL, NULL, &wt))
 1793       {
 1794         case 0: /* not ready */ return "not ready";
 1795         case -1: /*error*/      return "error";
 1796         case 1: /*ready ? */    break;
 1797       }
 1798     /* yes: read 1 char*/
 1799     /* if \n, check again with select else ungetc(c), ready*/
 1800       int c=s_getc(d->f_read);
 1801       //Print("try c=%d\n",c);
 1802       if (c== -1) return "eof"; /* eof or error */
 1803       else if (isdigit(c))
 1804       { s_ungetc(c,d->f_read); return "ready"; }
 1805       else if (c>' ')
 1806       {
 1807         Werror("unknown char in ssiLink(%d)",c);
 1808         return "error";
 1809       }
 1810       /* else: next char */
 1811     }
 1812   }
 1813   else if (strcmp(request, "read") == 0)
 1814   {
 1815     if (SI_LINK_R_OPEN_P(l) && (!s_iseof(d->f_read)) && (s_isready(d->f_read))) return "ready";
 1816     else return "not ready";
 1817   }
 1818   else if (strcmp(request, "write") == 0)
 1819   {
 1820     if (SI_LINK_W_OPEN_P(l)) return "ready";
 1821     else return "not ready";
 1822   }
 1823   else return "unknown status request";
 1824 }
 1825 
 1826 int slStatusSsiL(lists L, int timeout)
 1827 {
 1828 // input: L: a list with links of type
 1829 //           ssi-connect, ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch.
 1830 //           Note: Not every entry in L must be set.
 1831 //        timeout: timeout for select in micro-seconds
 1832 //           or -1 for infinity
 1833 //           or 0 for polling
 1834 // returns: ERROR (via Werror): L has wrong elements or link not open
 1835 //           -2: select returns an error
 1836 //           -1: the read state of all links is eof
 1837 //           0:  timeout (or polling): none ready,
 1838 //           i>0: (at least) L[i] is ready
 1839   si_link l;
 1840   ssiInfo *d;
 1841   int d_fd;
 1842   fd_set  mask, fdmask;
 1843   FD_ZERO(&fdmask);
 1844   FD_ZERO(&mask);
 1845   int max_fd=0; /* 1 + max fd in fd_set */
 1846 
 1847   /* timeout */
 1848   struct timeval wt;
 1849   struct timeval *wt_ptr=&wt;
 1850   int startingtime = getRTimer()/TIMER_RESOLUTION;  // in seconds
 1851   if (timeout== -1)
 1852   {
 1853     wt_ptr=NULL;
 1854   }
 1855   else
 1856   {
 1857     wt.tv_sec  = timeout / 1000000;
 1858     wt.tv_usec = timeout % 1000000;
 1859   }
 1860 
 1861   /* auxiliary variables */
 1862   int i;
 1863   int j;
 1864   int k;
 1865   int s;
 1866   char fdmaskempty;
 1867 
 1868   /* check the links and fill in fdmask */
 1869   /* check ssi links for ungetc_buf */
 1870   for(i=L->nr; i>=0; i--)
 1871   {
 1872     if (L->m[i].Typ()!=DEF_CMD)
 1873     {
 1874       if (L->m[i].Typ()!=LINK_CMD)
 1875       { WerrorS("all elements must be of type link"); return -2;}
 1876       l=(si_link)L->m[i].Data();
 1877       if(SI_LINK_OPEN_P(l)==0)
 1878       { WerrorS("all links must be open"); return -2;}
 1879       if (((strcmp(l->m->type,"ssi")!=0) && (strcmp(l->m->type,"MPtcp")!=0))
 1880       || ((strcmp(l->mode,"fork")!=0) && (strcmp(l->mode,"tcp")!=0)
 1881         && (strcmp(l->mode,"launch")!=0) && (strcmp(l->mode,"connect")!=0)))
 1882       {
 1883         WerrorS("all links must be of type ssi:fork, ssi:tcp, ssi:connect");
 1884         return -2;
 1885       }
 1886       if (strcmp(l->m->type,"ssi")==0)
 1887       {
 1888         d=(ssiInfo*)l->data;
 1889         d_fd=d->fd_read;
 1890         if (!s_isready(d->f_read))
 1891         {
 1892           FD_SET(d_fd, &fdmask);
 1893           if (d_fd > max_fd) max_fd=d_fd;
 1894         }
 1895         else
 1896           return i+1;
 1897       }
 1898       else
 1899       {
 1900         Werror("wrong link type >>%s<<",l->m->type);
 1901         return -2;
 1902       }
 1903     }
 1904   }
 1905   max_fd++;
 1906 
 1907 do_select:
 1908   /* copy fdmask to mask */
 1909   FD_ZERO(&mask);
 1910   for(k = 0; k < max_fd; k++)
 1911   {
 1912     if(FD_ISSET(k, &fdmask))
 1913     {
 1914       FD_SET(k, &mask);
 1915     }
 1916   }
 1917 
 1918   /* check with select: chars waiting: no -> not ready */
 1919   s = si_select(max_fd, &mask, NULL, NULL, wt_ptr);
 1920   if (s==-1)
 1921   {
 1922     WerrorS("error in select call");
 1923     return -2; /*error*/
 1924   }
 1925   if (s==0)
 1926   {
 1927     return 0; /*poll: not ready */
 1928   }
 1929   else /* s>0, at least one ready  (the number of fd which are ready is s)*/
 1930   {
 1931     j=0;
 1932     while (j<=max_fd) { if (FD_ISSET(j,&mask)) break; j++; }
 1933     for(i=L->nr; i>=0; i--)
 1934     {
 1935       if (L->m[i].rtyp==LINK_CMD)
 1936       {
 1937         l=(si_link)L->m[i].Data();
 1938         if (strcmp(l->m->type,"ssi")==0)
 1939         {
 1940           d=(ssiInfo*)l->data;
 1941           d_fd=d->fd_read;
 1942           if(j==d_fd) break;
 1943         }
 1944         else
 1945         {
 1946           Werror("wrong link type >>%s<<",l->m->type);
 1947           return -2;
 1948         }
 1949       }
 1950     }
 1951     // only ssi links:
 1952     loop
 1953     {
 1954       /* yes: read 1 char*/
 1955       /* if \n, check again with select else ungetc(c), ready*/
 1956       /* setting: d: current ssiInfo, j current fd, i current entry in L*/
 1957       int c=s_getc(d->f_read);
 1958       //Print("try c=%d\n",c);
 1959       if (c== -1) /* eof */
 1960       {
 1961         FD_CLR(j,&fdmask);
 1962         fdmaskempty = 1;
 1963         for(k = 0; k < max_fd; k++)
 1964         {
 1965           if(FD_ISSET(k, &fdmask))
 1966           {
 1967             fdmaskempty = 0;
 1968             break;
 1969           }
 1970         }
 1971         if(fdmaskempty)
 1972         {
 1973           return -1;
 1974         }
 1975         if(timeout != -1)
 1976         {
 1977           timeout = si_max(0,
 1978              timeout - 1000000*(getRTimer()/TIMER_RESOLUTION - startingtime));
 1979           wt.tv_sec  = timeout / 1000000;
 1980           wt.tv_usec = (timeout % 1000000);
 1981         }
 1982         goto do_select;
 1983       }
 1984 
 1985       else if (isdigit(c))
 1986       { s_ungetc(c,d->f_read); return i+1; }
 1987       else if (c>' ')
 1988       {
 1989         Werror("unknown char in ssiLink(%d)",c);
 1990         return -2;
 1991       }
 1992       /* else: next char */
 1993       goto do_select;
 1994     }
 1995   }
 1996 }
 1997 
 1998 int ssiBatch(const char *host, const char * port)
 1999 /* return 0 on success, >0 else*/
 2000 {
 2001   si_link l=(si_link) omAlloc0Bin(sip_link_bin);
 2002   char *buf=(char*)omAlloc(256);
 2003   sprintf(buf,"ssi:connect %s:%s",host,port);
 2004   slInit(l, buf);
 2005   omFreeSize(buf,256);
 2006   if (slOpen(l,SI_LINK_OPEN,NULL)) return 1;
 2007   SI_LINK_SET_RW_OPEN_P(l);
 2008 
 2009   idhdl id = enterid("link_ll", 0, LINK_CMD, &IDROOT, FALSE);
 2010   IDLINK(id) = l;
 2011 
 2012   loop
 2013   {
 2014     leftv h=ssiRead1(l); /*contains an exit.... */
 2015     if (feErrors != NULL && *feErrors != '\0')
 2016     {
 2017       // handle errors:
 2018       PrintS(feErrors); /* currently quite simple */
 2019       *feErrors = '\0';
 2020     }
 2021     ssiWrite(l,h);
 2022     h->CleanUp();
 2023     omFreeBin(h, sleftv_bin);
 2024   }
 2025   /* never reached*/
 2026   exit(0);
 2027 }
 2028 
 2029 STATIC_VAR int ssiReserved_P=0;
 2030 STATIC_VAR int ssiReserved_sockfd;
 2031 STATIC_VAR struct sockaddr_in ssiResverd_serv_addr;
 2032 STATIC_VAR int  ssiReserved_Clients;
 2033 int ssiReservePort(int clients)
 2034 {
 2035   if (ssiReserved_P!=0)
 2036   {
 2037     WerrorS("ERROR already a reserved port requested");
 2038     return 0;
 2039   }
 2040   int portno;
 2041   ssiReserved_sockfd = socket(AF_INET, SOCK_STREAM, 0);
 2042   if(ssiReserved_sockfd < 0)
 2043   {
 2044     WerrorS("ERROR opening socket");
 2045     return 0;
 2046   }
 2047   memset((char *) &ssiResverd_serv_addr,0, sizeof(ssiResverd_serv_addr));
 2048   portno = 1025;
 2049   ssiResverd_serv_addr.sin_family = AF_INET;
 2050   ssiResverd_serv_addr.sin_addr.s_addr = INADDR_ANY;
 2051   do
 2052   {
 2053     portno++;
 2054     ssiResverd_serv_addr.sin_port = htons(portno);
 2055     if(portno > 50000)
 2056     {
 2057       WerrorS("ERROR on binding (no free port available?)");
 2058       return 0;
 2059     }
 2060   }
 2061   while(bind(ssiReserved_sockfd, (struct sockaddr *) &ssiResverd_serv_addr, sizeof(ssiResverd_serv_addr)) < 0);
 2062   ssiReserved_P=portno;
 2063   listen(ssiReserved_sockfd,clients);
 2064   ssiReserved_Clients=clients;
 2065   return portno;
 2066 }
 2067 
 2068 EXTERN_VAR si_link_extension si_link_root;
 2069 si_link ssiCommandLink()
 2070 {
 2071   if (ssiReserved_P==0)
 2072   {
 2073     WerrorS("ERROR no reserved port requested");
 2074     return NULL;
 2075   }
 2076   struct sockaddr_in cli_addr;
 2077   int clilen = sizeof(cli_addr);
 2078   int newsockfd = si_accept(ssiReserved_sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
 2079   if(newsockfd < 0)
 2080   {
 2081     Werror("ERROR on accept (errno=%d)",errno);
 2082     return NULL;
 2083   }
 2084   si_link l=(si_link) omAlloc0Bin(sip_link_bin);
 2085   si_link_extension s = si_link_root;
 2086   si_link_extension prev = s;
 2087   while (strcmp(s->type, "ssi") != 0)
 2088   {
 2089     if (s->next == NULL)
 2090     {
 2091       prev = s;
 2092       s = NULL;
 2093       break;
 2094     }
 2095     else
 2096     {
 2097       s = s->next;
 2098     }
 2099   }
 2100   if (s != NULL)
 2101     l->m = s;
 2102   else
 2103   {
 2104     si_link_extension ns = (si_link_extension)omAlloc0Bin(s_si_link_extension_bin);
 2105     prev->next=slInitSsiExtension(ns);
 2106     l->m = prev->next;
 2107   }
 2108   l->name=omStrDup("");
 2109   l->mode=omStrDup("tcp");
 2110   l->ref=1;
 2111   ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
 2112   l->data=d;
 2113   d->fd_read = newsockfd;
 2114   d->fd_write = newsockfd;
 2115   d->f_read = s_open(newsockfd);
 2116   d->f_write = fdopen(newsockfd, "w");
 2117   SI_LINK_SET_RW_OPEN_P(l);
 2118   ssiReserved_Clients--;
 2119   if (ssiReserved_Clients<=0)
 2120   {
 2121     ssiReserved_P=0;
 2122     si_close(ssiReserved_sockfd);
 2123   }
 2124   return l;
 2125 }
 2126 /*---------------------------------------------------------------------*/
 2127 /**
 2128  * @brief additional default signal handler
 2129 
 2130   // some newer Linux version cannot have SIG_IGN for SIGCHLD,
 2131   // so use this nice routine here:
 2132   //  SuSe 9.x reports -1 always
 2133   //  Redhat 9.x/FC x reports sometimes -1
 2134   // see also: hpux_system
 2135   // also needed by getrusage (timer etc.)
 2136 
 2137  @param[in] sig
 2138 **/
 2139 /*---------------------------------------------------------------------*/
 2140 void sig_chld_hdl(int)
 2141 {
 2142   pid_t kidpid;
 2143   int status;
 2144 
 2145   loop
 2146   {
 2147     kidpid = si_waitpid(-1, &status, WNOHANG);
 2148     if (kidpid==-1)
 2149     {
 2150       /* continue on interruption (EINTR): */
 2151       if (errno == EINTR) continue;
 2152       /* break on anything else (EINVAL or ECHILD according to manpage): */
 2153       break;
 2154     }
 2155     else if (kidpid==0) break; /* no more children to process, so break */
 2156 
 2157     //printf("Child %ld terminated\n", kidpid);
 2158     link_list hh=ssiToBeClosed;
 2159     while((hh!=NULL)&&(ssiToBeClosed_inactive))
 2160     {
 2161       if((hh->l!=NULL) && (hh->l->m->Open==ssiOpen))
 2162       {
 2163         ssiInfo *d = (ssiInfo *)hh->l->data;
 2164         if(d->pid==kidpid)
 2165         {
 2166           if(ssiToBeClosed_inactive)
 2167           {
 2168             ssiToBeClosed_inactive=FALSE;
 2169             slClose(hh->l);
 2170             ssiToBeClosed_inactive=TRUE;
 2171             break;
 2172           }
 2173           else break;
 2174         }
 2175         else hh=(link_list)hh->next;
 2176       }
 2177       else hh=(link_list)hh->next;
 2178     }
 2179   }
 2180 }
 2181 
 2182 static BOOLEAN DumpSsiIdhdl(si_link l, idhdl h)
 2183 {
 2184   int type_id = IDTYP(h);
 2185 
 2186   // C-proc not to be dumped, also LIB-proc not
 2187   if (type_id == PROC_CMD)
 2188   {
 2189     if (IDPROC(h)->language == LANG_C) return FALSE;
 2190     if (IDPROC(h)->libname != NULL) return FALSE;
 2191   }
 2192   // do not dump links
 2193   if (type_id == LINK_CMD) return FALSE;
 2194 
 2195   // do not dump ssi internal rings: ssiRing*
 2196   if ((type_id == RING_CMD) && (strncmp(IDID(h),"ssiRing",7)==0))
 2197     return FALSE;
 2198 
 2199   // do not dump default cring:
 2200   if (type_id == CRING_CMD)
 2201   {
 2202     if (strcmp(IDID(h),"ZZ")==0) return FALSE;
 2203     if (strcmp(IDID(h),"QQ")==0) return FALSE;
 2204     #ifdef SINGULAR_4_2
 2205     if (strcmp(IDID(h),"AE")==0) return FALSE;
 2206     if (strcmp(IDID(h),"QAE")==0) return FALSE;
 2207     #endif
 2208   }
 2209 
 2210   command D=(command)omAlloc0(sizeof(*D));
 2211   sleftv tmp;
 2212   memset(&tmp,0,sizeof(tmp));
 2213   tmp.rtyp=COMMAND;
 2214   tmp.data=D;
 2215 
 2216   if (type_id == PACKAGE_CMD)
 2217   {
 2218     // do not dump Top, Standard
 2219     if ((strcmp(IDID(h), "Top") == 0)
 2220     || (strcmp(IDID(h), "Standard") == 0))
 2221     {
 2222       omFreeSize(D,sizeof(*D));
 2223       return FALSE;
 2224     }
 2225     package p=(package)IDDATA(h);
 2226     // dump Singular-packages as LIB("...");
 2227     if (p->language==LANG_SINGULAR)
 2228     {
 2229       D->op=LOAD_CMD;
 2230       D->argc=2;
 2231       D->arg1.rtyp=STRING_CMD;
 2232       D->arg1.data=p->libname;
 2233       D->arg2.rtyp=STRING_CMD;
 2234       D->arg2.data=(char*)"with";
 2235       ssiWrite(l,&tmp);
 2236       omFreeSize(D,sizeof(*D));
 2237       return FALSE;
 2238     }
 2239     // dump Singular-packages as load("...");
 2240     else if (p->language==LANG_C)
 2241     {
 2242       D->op=LOAD_CMD;
 2243       D->argc=1;
 2244       D->arg1.rtyp=STRING_CMD;
 2245       D->arg1.data=p->libname;
 2246       ssiWrite(l,&tmp);
 2247       omFreeSize(D,sizeof(*D));
 2248       return FALSE;
 2249     }
 2250   }
 2251 
 2252   // put type and name
 2253   //Print("generic dump:%s,%s\n",IDID(h),Tok2Cmdname(IDTYP(h)));
 2254   D->op='=';
 2255   D->argc=2;
 2256   D->arg1.rtyp=DEF_CMD;
 2257   D->arg1.name=IDID(h);
 2258   D->arg2.rtyp=IDTYP(h);
 2259   D->arg2.data=IDDATA(h);
 2260   ssiWrite(l,&tmp);
 2261   omFreeSize(D,sizeof(*D));
 2262   return FALSE;
 2263 }
 2264 static BOOLEAN ssiDumpIter(si_link l, idhdl h)
 2265 {
 2266   if (h == NULL) return FALSE;
 2267 
 2268   if (ssiDumpIter(l, IDNEXT(h))) return TRUE;
 2269 
 2270   // need to set the ring before writing it, otherwise we get in
 2271   // trouble with minpoly
 2272   if (IDTYP(h) == RING_CMD)
 2273     rSetHdl(h);
 2274 
 2275   if (DumpSsiIdhdl(l, h)) return TRUE;
 2276 
 2277   // do not dump ssi internal rings: ssiRing*
 2278   // but dump objects of all other rings
 2279   if ((IDTYP(h) == RING_CMD)
 2280   && (strncmp(IDID(h),"ssiRing",7)!=0))
 2281     return ssiDumpIter(l, IDRING(h)->idroot);
 2282   else
 2283     return FALSE;
 2284 }
 2285 BOOLEAN ssiDump(si_link l)
 2286 {
 2287   idhdl h = IDROOT, rh = currRingHdl;
 2288   BOOLEAN status = ssiDumpIter(l, h);
 2289 
 2290   //if (! status ) status = DumpAsciiMaps(fd, h, NULL);
 2291 
 2292   if (currRingHdl != rh) rSetHdl(rh);
 2293   //fprintf(fd, "option(set, intvec(%d, %d));\n", si_opt_1, si_opt_2);
 2294 
 2295   return status;
 2296 }
 2297 BOOLEAN ssiGetDump(si_link l)
 2298 {
 2299   ssiInfo *d=(ssiInfo*)l->data;
 2300   loop
 2301   {
 2302     if (!SI_LINK_OPEN_P(l)) break;
 2303     if (s_iseof(d->f_read)) break;
 2304     leftv h=ssiRead1(l); /*contains an exit.... */
 2305     if (feErrors != NULL && *feErrors != '\0')
 2306     {
 2307       // handle errors:
 2308       PrintS(feErrors); /* currently quite simple */
 2309       return TRUE;
 2310       *feErrors = '\0';
 2311     }
 2312     h->CleanUp();
 2313     omFreeBin(h, sleftv_bin);
 2314   }
 2315   return FALSE;
 2316 }
 2317 // ----------------------------------------------------------------
 2318 // format
 2319 // 1 int %d
 2320 // 2 string <len> %s
 2321 // 3 number
 2322 // 4 bigint 4 %d or 3 <mpz_t>
 2323 // 5 ring
 2324 // 6 poly
 2325 // 7 ideal
 2326 // 8 matrix
 2327 // 9 vector
 2328 // 10 module
 2329 // 11 command
 2330 // 12 def <len> %s
 2331 // 13 proc <len> %s
 2332 // 14 list %d <elem1> ....
 2333 // 15 setring .......
 2334 // 16 nothing
 2335 // 17 intvec <len> ...
 2336 // 18 intmat
 2337 // 19 bigintmat <r> <c> ...
 2338 // 20 blackbox <name> 1 <len> ...
 2339 // 21 attrib <bit-attrib> <len> <a-name1> <val1>... <data>
 2340 // 22 smatrix
 2341 // 23 0 <log(bitmask)> ring properties: max.exp.
 2342 // 23 1 <log(bitmask)> <r->IsLPRing> ring properties:LPRing
 2343 // 23 2 <matrix C> <matrix D> ring properties: PLuralRing
 2344 //
 2345 // 98: verify version: <ssi-version> <MAX_TOK> <OPT1> <OPT2>
 2346 // 99: quit Singular