source: git/Singular/links/ssiLink.cc @ 1f91b9

fieker-DuValspielwiese
Last change on this file since 1f91b9 was 1f91b9, checked in by Hans Schoenemann <hannes@…>, 3 years ago
rIncRefCnt, rDecRefCnt
  • Property mode set to 100644
File size: 59.5 KB
Line 
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
62VAR link_list ssiToBeClosed=NULL;
63VAR volatile BOOLEAN ssiToBeClosed_inactive=TRUE;
64
65// forward declarations:
66void ssiWritePoly_R(const ssiInfo *d, int typ, poly p, const ring r);
67void ssiWriteIdeal_R(const ssiInfo *d, int typ,const ideal I, const ring r);
68poly ssiReadPoly_R(const ssiInfo *D, const ring r);
69ideal ssiReadIdeal_R(const ssiInfo *d,const ring r);
70
71// the helper functions:
72BOOLEAN 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}
117void 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:
148void 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
154void 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
160void ssiWriteBigInt(const ssiInfo *d, const number n)
161{
162 n_WriteFd(n,d,coeffs_BIGINT);
163}
164
165void 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
193void ssiWriteNumber(const ssiInfo *d, const number n)
194{
195  ssiWriteNumber_CF(d,n,d->r->cf);
196}
197
198void 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
301void 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}
324void 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
342void ssiWritePoly(const ssiInfo *d, int typ, poly p)
343{
344  ssiWritePoly_R(d,typ,p,d->r);
345}
346
347void 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}
377void ssiWriteIdeal(const ssiInfo *d, int typ,const ideal I)
378{
379  ssiWriteIdeal_R(d,typ,I,d->r);
380}
381
382void 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
395void 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
405void 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}
416void 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}
425void 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
435void 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
445char *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
458int ssiReadInt(s_buff fich)
459{
460  return s_readint(fich);
461}
462
463number 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
487number 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
497number ssiReadNumber(ssiInfo *d)
498{
499  return ssiReadNumber_CF(d,d->r->cf);
500}
501
502ring 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    return r;
622  }
623}
624
625poly ssiReadPoly_R(const ssiInfo *d, const ring r)
626{
627// < # of terms> < term1> < .....
628  int n,i,l;
629  n=ssiReadInt(d->f_read); // # of terms
630  //Print("poly: terms:%d\n",n);
631  poly p;
632  poly ret=NULL;
633  poly prev=NULL;
634  for(l=0;l<n;l++) // read n terms
635  {
636// coef,comp.exp1,..exp N
637    p=p_Init(r,r->PolyBin);
638    pSetCoeff0(p,ssiReadNumber_CF(d,r->cf));
639    int D;
640    D=s_readint(d->f_read);
641    p_SetComp(p,D,r);
642    for(i=1;i<=rVar(r);i++)
643    {
644      D=s_readint(d->f_read);
645      p_SetExp(p,i,D,r);
646    }
647    p_Setm(p,r);
648    p_Test(p,r);
649    if (ret==NULL) ret=p;
650    else           pNext(prev)=p;
651    prev=p;
652 }
653 return ret;
654}
655
656poly ssiReadPoly(ssiInfo *d)
657{
658  return ssiReadPoly_R(d,d->r);
659}
660
661ideal ssiReadIdeal_R(const ssiInfo *d,const ring r)
662{
663// < # of terms> < term1> < .....
664  int n,i;
665  ideal I;
666  n=s_readint(d->f_read);
667  I=idInit(n,1); // will be fixed later for module/smatrix
668  for(i=0;i<IDELEMS(I);i++) // read n terms
669  {
670    I->m [i]=ssiReadPoly_R(d,r);
671  }
672  return I;
673}
674
675ideal ssiReadIdeal(ssiInfo *d)
676{
677  return ssiReadIdeal_R(d,d->r);
678}
679
680matrix ssiReadMatrix(ssiInfo *d)
681{
682  int n,m;
683  m=s_readint(d->f_read);
684  n=s_readint(d->f_read);
685  matrix M=mpNew(m,n);
686  poly p;
687  for(int i=1;i<=MATROWS(M);i++)
688    for(int j=1;j<=MATCOLS(M);j++)
689    {
690      p=ssiReadPoly(d);
691      MATELEM(M,i,j)=p;
692    }
693  return M;
694}
695
696command ssiReadCommand(si_link l)
697{
698  ssiInfo *d=(ssiInfo*)l->data;
699  // syntax: <num ops> <operation> <op1> <op2> ....
700  command D=(command)omAlloc0(sizeof(*D));
701  int argc,op;
702  argc=s_readint(d->f_read);
703  op=s_readint(d->f_read);
704  D->argc=argc; D->op=op;
705  leftv v;
706  if (argc >0)
707  {
708    v=ssiRead1(l);
709    memcpy(&(D->arg1),v,sizeof(*v));
710    omFreeBin(v,sleftv_bin);
711  }
712  if (argc <4)
713  {
714    if (D->argc >1)
715    {
716      v=ssiRead1(l);
717      memcpy(&(D->arg2),v,sizeof(*v));
718      omFreeBin(v,sleftv_bin);
719    }
720    if (D->argc >2)
721    {
722      v=ssiRead1(l);
723      memcpy(&(D->arg3),v,sizeof(*v));
724      omFreeBin(v,sleftv_bin);
725    }
726  }
727  else
728  {
729    leftv prev=&(D->arg1);
730    argc--;
731    while(argc >0)
732    {
733      v=ssiRead1(l);
734      prev->next=v;
735      prev=v;
736      argc--;
737    }
738  }
739  return D;
740}
741
742procinfov ssiReadProc(const ssiInfo *d)
743{
744  char *s=ssiReadString(d);
745  procinfov p=(procinfov)omAlloc0Bin(procinfo_bin);
746  p->language=LANG_SINGULAR;
747  p->libname=omStrDup("");
748  p->procname=omStrDup("");
749  p->data.s.body=s;
750  return p;
751}
752lists ssiReadList(si_link l)
753{
754  ssiInfo *d=(ssiInfo*)l->data;
755  int nr;
756  nr=s_readint(d->f_read);
757  lists L=(lists)omAlloc0Bin(slists_bin);
758  L->Init(nr);
759
760  int i;
761  leftv v;
762  for(i=0;i<=L->nr;i++)
763  {
764    v=ssiRead1(l);
765    memcpy(&(L->m[i]),v,sizeof(*v));
766    omFreeBin(v,sleftv_bin);
767  }
768  return L;
769}
770intvec* ssiReadIntvec(const ssiInfo *d)
771{
772  int nr;
773  nr=s_readint(d->f_read);
774  intvec *v=new intvec(nr);
775  for(int i=0;i<nr;i++)
776  {
777    (*v)[i]=s_readint(d->f_read);
778  }
779  return v;
780}
781intvec* ssiReadIntmat(const ssiInfo *d)
782{
783  int r,c;
784  r=s_readint(d->f_read);
785  c=s_readint(d->f_read);
786  intvec *v=new intvec(r,c,0);
787  for(int i=0;i<r*c;i++)
788  {
789    (*v)[i]=s_readint(d->f_read);
790  }
791  return v;
792}
793bigintmat* ssiReadBigintmat(const ssiInfo *d)
794{
795  int r,c;
796  r=s_readint(d->f_read);
797  c=s_readint(d->f_read);
798  bigintmat *v=new bigintmat(r,c,coeffs_BIGINT);
799  for(int i=0;i<r*c;i++)
800  {
801    (*v)[i]=ssiReadBigInt(d);
802  }
803  return v;
804}
805
806void ssiReadBlackbox(leftv res, si_link l)
807{
808  ssiInfo *d=(ssiInfo*)l->data;
809  int throwaway=s_readint(d->f_read);
810  char *name=ssiReadString(d);
811  int tok;
812  blackboxIsCmd(name,tok);
813  if (tok>MAX_TOK)
814  {
815    ring save_ring=currRing;
816    idhdl save_hdl=currRingHdl;
817    blackbox *b=getBlackboxStuff(tok);
818    res->rtyp=tok;
819    b->blackbox_deserialize(&b,&(res->data),l);
820    if (save_ring!=currRing)
821    {
822      rChangeCurrRing(save_ring);
823      if (save_hdl!=NULL) rSetHdl(save_hdl);
824      else currRingHdl=NULL;
825    }
826  }
827  else
828  {
829    Werror("blackbox %s not found",name);
830  }
831  omFree(name);
832}
833
834void ssiReadAttrib(leftv res, si_link l)
835{
836  ssiInfo *d=(ssiInfo*)l->data;
837  BITSET fl=(BITSET)s_readint(d->f_read);
838  int nr_of_attr=s_readint(d->f_read);
839  if (nr_of_attr>0)
840  {
841    for(int i=1;i<nr_of_attr;i++)
842    {
843    }
844  }
845  leftv tmp=ssiRead1(l);
846  memcpy(res,tmp,sizeof(sleftv));
847  memset(tmp,0,sizeof(sleftv));
848  omFreeBin(tmp,sleftv_bin);
849  if (nr_of_attr>0)
850  {
851  }
852  res->flag=fl;
853}
854void ssiReadRingProperties(si_link l)
855{
856  ssiInfo *d=(ssiInfo*)l->data;
857  int what=s_readint(d->f_read);
858  switch(what)
859  {
860    case 0: // bitmask
861    {
862      int lb=s_readint(d->f_read);
863      unsigned long bm=~0L;
864      bm=bm<<lb;
865      bm=~bm;
866      rUnComplete(d->r);
867      d->r->bitmask=bm;
868      rComplete(d->r);
869      break;
870    }
871    case 1: // LPRing
872    {
873      int lb=s_readint(d->f_read);
874      int isLPring=s_readint(d->f_read);
875      unsigned long bm=~0L;
876      bm=bm<<lb;
877      bm=~bm;
878      rUnComplete(d->r);
879      d->r->bitmask=bm;
880      d->r->isLPring=isLPring;
881      rComplete(d->r);
882      break;
883    }
884    case 2: // Plural rings
885    {
886      matrix C=ssiReadMatrix(d);
887      matrix D=ssiReadMatrix(d);
888      nc_CallPlural(C,D,NULL,NULL,d->r,true,true,false,d->r,false);
889      break;
890    }
891  }
892}
893//**************************************************************************/
894
895BOOLEAN ssiOpen(si_link l, short flag, leftv u)
896{
897  if (l!=NULL)
898  {
899    const char *mode;
900    ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
901    if (flag & SI_LINK_OPEN)
902    {
903      if (l->mode[0] != '\0' && (strcmp(l->mode, "r") == 0))
904        flag = SI_LINK_READ;
905      else flag = SI_LINK_WRITE;
906    }
907
908    if (flag == SI_LINK_READ) mode = "r";
909    else if (strcmp(l->mode, "w") == 0) mode = "w";
910    else if (strcmp(l->mode, "fork") == 0) mode = "fork";
911    else if (strcmp(l->mode, "tcp") == 0) mode = "tcp";
912    else if (strcmp(l->mode, "connect") == 0) mode = "connect";
913    else mode = "a";
914
915
916    SI_LINK_SET_OPEN_P(l, flag);
917    if(l->data!=NULL) omFreeSize(l->data,sizeof(ssiInfo));
918    l->data=d;
919    omFree(l->mode);
920    l->mode = omStrDup(mode);
921
922    if (l->name[0] == '\0')
923    {
924      if (strcmp(mode,"fork")==0)
925      {
926        link_list n=(link_list)omAlloc(sizeof(link_struct));
927        n->u=u;
928        n->l=l;
929        n->next=(void *)ssiToBeClosed;
930        ssiToBeClosed=n;
931
932        int pc[2];
933        int cp[2];
934        pipe(pc);
935        pipe(cp);
936        pid_t pid = fork();
937        if (pid == -1 && errno == EAGAIN)   // RLIMIT_NPROC too low?
938        {
939          raise_rlimit_nproc();
940          pid = fork();
941        }
942        if (pid == -1)
943        {
944          WerrorS("could not fork");
945        }
946        if (pid==0) /*fork: child*/
947        {
948          /* block SIGINT */
949          sigset_t sigint;
950          sigemptyset(&sigint);
951          sigaddset(&sigint, SIGINT);
952          sigprocmask(SIG_BLOCK, &sigint, NULL);
953          /* set #cpu to 1 for the child:*/
954          feSetOptValue(FE_OPT_CPUS,1);
955
956          link_list hh=(link_list)ssiToBeClosed->next;
957          /* we know: l is the first entry in ssiToBeClosed-list */
958          while(hh!=NULL)
959          {
960            SI_LINK_SET_CLOSE_P(hh->l);
961            ssiInfo *dd=(ssiInfo*)hh->l->data;
962            s_close(dd->f_read);
963            fclose(dd->f_write);
964            if (dd->r!=NULL) rKill(dd->r);
965            omFreeSize((ADDRESS)dd,(sizeof *dd));
966            hh->l->data=NULL;
967            link_list nn=(link_list)hh->next;
968            omFree(hh);
969            hh=nn;
970          }
971          ssiToBeClosed->next=NULL;
972#ifdef HAVE_SIMPLEIPC
973          memset(sem_acquired, 0, SIPC_MAX_SEMAPHORES*sizeof(sem_acquired[0]));
974#endif   // HAVE_SIMPLEIPC
975          si_close(pc[1]); si_close(cp[0]);
976          d->f_write=fdopen(cp[1],"w");
977          d->f_read=s_open(pc[0]);
978          d->fd_read=pc[0];
979          d->fd_write=cp[1];
980          //d->r=currRing;
981          //if (d->r!=NULL) d->r->ref++;
982          l->data=d;
983          omFree(l->mode);
984          l->mode = omStrDup(mode);
985          singular_in_batchmode=TRUE;
986          SI_LINK_SET_RW_OPEN_P(l);
987          //myynest=0;
988          fe_fgets_stdin=fe_fgets_dummy;
989          if ((u!=NULL)&&(u->rtyp==IDHDL))
990          {
991            idhdl h=(idhdl)u->data;
992            h->lev=0;
993          }
994          loop
995          {
996            if (!SI_LINK_OPEN_P(l)) m2_end(0);
997            if(d->f_read->is_eof) m2_end(0);
998            leftv h=ssiRead1(l); /*contains an exit.... */
999            if (feErrors != NULL && *feErrors != '\0')
1000            {
1001              // handle errors:
1002              PrintS(feErrors); /* currently quite simple */
1003              *feErrors = '\0';
1004            }
1005            ssiWrite(l,h);
1006            h->CleanUp();
1007            omFreeBin(h, sleftv_bin);
1008          }
1009          /* never reached*/
1010        }
1011        else if (pid>0) /*fork: parent*/
1012        {
1013          d->pid=pid;
1014          si_close(pc[0]); si_close(cp[1]);
1015          d->f_write=fdopen(pc[1],"w");
1016          d->f_read=s_open(cp[0]);
1017          d->fd_read=cp[0];
1018          d->fd_write=pc[1];
1019          SI_LINK_SET_RW_OPEN_P(l);
1020          d->send_quit_at_exit=1;
1021          //d->r=currRing;
1022          //if (d->r!=NULL) d->r->ref++;
1023        }
1024        else
1025        {
1026          Werror("fork failed (%d)",errno);
1027          l->data=NULL;
1028          omFree(d);
1029          return TRUE;
1030        }
1031      }
1032      // ---------------------------------------------------------------------
1033      else if (strcmp(mode,"tcp")==0)
1034      {
1035        int sockfd, newsockfd, portno, clilen;
1036        struct sockaddr_in serv_addr, cli_addr;
1037        sockfd = socket(AF_INET, SOCK_STREAM, 0);
1038        if(sockfd < 0)
1039        {
1040          WerrorS("ERROR opening socket");
1041          l->data=NULL;
1042          SI_LINK_CLOSE_P(l);
1043          omFree(d);
1044          return TRUE;
1045        }
1046        memset((char *) &serv_addr,0, sizeof(serv_addr));
1047        portno = 1025;
1048        serv_addr.sin_family = AF_INET;
1049        serv_addr.sin_addr.s_addr = INADDR_ANY;
1050        do
1051        {
1052          portno++;
1053          serv_addr.sin_port = htons(portno);
1054          if(portno > 50000)
1055          {
1056            WerrorS("ERROR on binding (no free port available?)");
1057            l->data=NULL;
1058            SI_LINK_CLOSE_P(l);
1059            omFree(d);
1060            return TRUE;
1061          }
1062        }
1063        while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
1064        Print("waiting on port %d\n", portno);mflush();
1065        listen(sockfd,1);
1066        newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
1067        if(newsockfd < 0)
1068        {
1069          WerrorS("ERROR on accept");
1070          l->data=NULL;
1071          SI_LINK_CLOSE_P(l);
1072          omFree(d);
1073          return TRUE;
1074        }
1075        PrintS("client accepted\n");
1076        d->fd_read = newsockfd;
1077        d->fd_write = newsockfd;
1078        d->f_read = s_open(newsockfd);
1079        d->f_write = fdopen(newsockfd, "w");
1080        SI_LINK_SET_RW_OPEN_P(l);
1081        si_close(sockfd);
1082      }
1083      // no ssi-Link on stdin or stdout
1084      else
1085      {
1086        Werror("invalid mode >>%s<< for ssi",mode);
1087        l->data=NULL;
1088        SI_LINK_CLOSE_P(l);
1089        omFree(d);
1090        return TRUE;
1091      }
1092    }
1093    // =========================================================================
1094    else /*l->name=NULL*/
1095    {
1096      // tcp mode
1097      if(strcmp(mode,"tcp")==0)
1098      {
1099        int sockfd, newsockfd, portno, clilen;
1100        struct sockaddr_in serv_addr, cli_addr;
1101        sockfd = socket(AF_INET, SOCK_STREAM, 0);
1102        if(sockfd < 0)
1103        {
1104          WerrorS("ERROR opening socket");
1105          l->data=NULL;
1106          SI_LINK_CLOSE_P(l);
1107          omFree(d);
1108          return TRUE;
1109        }
1110        memset((char *) &serv_addr,0, sizeof(serv_addr));
1111        portno = 1025;
1112        serv_addr.sin_family = AF_INET;
1113        serv_addr.sin_addr.s_addr = INADDR_ANY;
1114        do
1115        {
1116          portno++;
1117          serv_addr.sin_port = htons(portno);
1118          if(portno > 50000)
1119          {
1120            WerrorS("ERROR on binding (no free port available?)");
1121            l->data=NULL;
1122            SI_LINK_CLOSE_P(l);
1123            return TRUE;
1124          }
1125        }
1126        while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
1127        //Print("waiting on port %d\n", portno);mflush();
1128        listen(sockfd,1);
1129        char* cli_host = (char*)omAlloc(256);
1130        char* path = (char*)omAlloc(1024);
1131        int r = si_sscanf(l->name,"%255[^:]:%s",cli_host,path);
1132        if(r == 0)
1133        {
1134          WerrorS("ERROR: no host specified");
1135          l->data=NULL;
1136          SI_LINK_CLOSE_P(l);
1137          omFree(d);
1138          omFree(path);
1139          omFree(cli_host);
1140          return TRUE;
1141        }
1142        else if(r == 1)
1143        {
1144          WarnS("program not specified, using /usr/local/bin/Singular");
1145          Warn("in line >>%s<<",my_yylinebuf);
1146          strcpy(path,"/usr/local/bin/Singular");
1147        }
1148        char* ssh_command = (char*)omAlloc(256);
1149        char* ser_host = (char*)omAlloc(64);
1150        gethostname(ser_host,64);
1151        if (strcmp(cli_host,"localhost")==0) /*avoid "ssh localhost" as key may change*/
1152          sprintf(ssh_command,"%s -q --batch --link=ssi --MPhost=%s --MPport=%d &",path,ser_host,portno);
1153        else
1154          sprintf(ssh_command,"ssh %s %s -q --batch --link=ssi --MPhost=%s --MPport=%d &",cli_host,path,ser_host,portno);
1155        //Print("client on %s started:%s\n",cli_host,path);
1156        omFree(path);
1157        omFree(cli_host);
1158        if (TEST_OPT_PROT) { Print("running >>%s<<\n",ssh_command); }
1159        system(ssh_command);
1160        omFree(ssh_command);
1161        omFree(ser_host);
1162        clilen = sizeof(cli_addr);
1163        newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
1164        if(newsockfd < 0)
1165        {
1166          WerrorS("ERROR on accept");
1167          l->data=NULL;
1168          SI_LINK_CLOSE_P(l);
1169          omFree(d);
1170          return TRUE;
1171        }
1172        //PrintS("client accepted\n");
1173        d->fd_read = newsockfd;
1174        d->fd_write = newsockfd;
1175        d->f_read = s_open(newsockfd);
1176        d->f_write = fdopen(newsockfd, "w");
1177        si_close(sockfd);
1178        SI_LINK_SET_RW_OPEN_P(l);
1179        d->send_quit_at_exit=1;
1180        link_list newlink=(link_list)omAlloc(sizeof(link_struct));
1181        newlink->u=u;
1182        newlink->l=l;
1183        newlink->next=(void *)ssiToBeClosed;
1184        ssiToBeClosed=newlink;
1185        fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2);
1186      }
1187      // ----------------------------------------------------------------------
1188      else if(strcmp(mode,"connect")==0)
1189      {
1190        char* host = (char*)omAlloc(256);
1191        int sockfd, portno;
1192        struct sockaddr_in serv_addr;
1193        struct hostent *server;
1194
1195        si_sscanf(l->name,"%255[^:]:%d",host,&portno);
1196        //Print("connect to host %s, port %d\n",host,portno);mflush();
1197        if (portno!=0)
1198        {
1199          sockfd = socket(AF_INET, SOCK_STREAM, 0);
1200          if (sockfd < 0)
1201          {
1202            WerrorS("ERROR opening socket");
1203            SI_LINK_CLOSE_P(l);
1204            return TRUE;
1205          }
1206          server = gethostbyname(host);
1207          if (server == NULL)
1208          {
1209            WerrorS("ERROR, no such host");
1210            SI_LINK_CLOSE_P(l);
1211            return TRUE;
1212          }
1213          memset((char *) &serv_addr, 0, sizeof(serv_addr));
1214          serv_addr.sin_family = AF_INET;
1215          memcpy((char *)&serv_addr.sin_addr.s_addr,
1216                (char *)server->h_addr,
1217                server->h_length);
1218          serv_addr.sin_port = htons(portno);
1219          if (si_connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
1220          {
1221            Werror("ERROR connecting(errno=%d)",errno);
1222            SI_LINK_CLOSE_P(l);
1223            return TRUE;
1224          }
1225          //PrintS("connected\n");mflush();
1226          d->f_read=s_open(sockfd);
1227          d->fd_read=sockfd;
1228          d->f_write=fdopen(sockfd,"w");
1229          d->fd_write=sockfd;
1230          SI_LINK_SET_RW_OPEN_P(l);
1231          omFree(host);
1232        }
1233        else
1234        {
1235          l->data=NULL;
1236          SI_LINK_CLOSE_P(l);
1237          omFree(d);
1238          return TRUE;
1239        }
1240      }
1241      // ======================================================================
1242      else
1243      {
1244        // normal link to a file
1245        FILE *outfile;
1246        char *filename=l->name;
1247
1248        if(filename[0]=='>')
1249        {
1250          if (filename[1]=='>')
1251          {
1252            filename+=2;
1253            mode = "a";
1254          }
1255          else
1256          {
1257            filename++;
1258            mode="w";
1259          }
1260        }
1261        outfile=myfopen(filename,mode);
1262        if (outfile!=NULL)
1263        {
1264          if (strcmp(l->mode,"r")==0)
1265          {
1266            fclose(outfile);
1267            d->f_read=s_open_by_name(filename);
1268          }
1269          else
1270          {
1271            d->f_write = outfile;
1272            fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2);
1273          }
1274        }
1275        else
1276        {
1277          omFree(d);
1278          l->data=NULL;
1279          SI_LINK_CLOSE_P(l);
1280          return TRUE;
1281        }
1282      }
1283    }
1284  }
1285
1286  return FALSE;
1287}
1288
1289//**************************************************************************/
1290BOOLEAN ssiPrepClose(si_link l)
1291{
1292  if (l!=NULL)
1293  {
1294    SI_LINK_SET_CLOSE_P(l);
1295    ssiInfo *d = (ssiInfo *)l->data;
1296    if (d!=NULL)
1297    {
1298      if (d->send_quit_at_exit)
1299      {
1300        fputs("99\n",d->f_write);
1301        fflush(d->f_write);
1302      }
1303      d->quit_sent=1;
1304    }
1305  }
1306  return FALSE;
1307}
1308
1309BOOLEAN ssiClose(si_link l)
1310{
1311  if (l!=NULL)
1312  {
1313    SI_LINK_SET_CLOSE_P(l);
1314    ssiInfo *d = (ssiInfo *)l->data;
1315    if (d!=NULL)
1316    {
1317      // send quit signal
1318      if ((d->send_quit_at_exit)
1319      && (d->quit_sent==0))
1320      {
1321        fputs("99\n",d->f_write);
1322        fflush(d->f_write);
1323      }
1324      // clean ring
1325      if (d->r!=NULL) rKill(d->r);
1326      // did the child to stop ?
1327      si_waitpid(d->pid,NULL,WNOHANG);
1328      if ((d->pid!=0)
1329      && (kill(d->pid,0)==0)) // child is still running
1330      {
1331        struct timespec t;
1332        t.tv_sec=0;
1333        t.tv_nsec=100000000; // <=100 ms
1334        struct timespec rem;
1335        int r;
1336        loop
1337        {
1338          // wait till signal or time rem:
1339          r = nanosleep(&t, &rem);
1340          t = rem;
1341          // child finished:
1342          if (si_waitpid(d->pid,NULL,WNOHANG) != 0) break;
1343          // other signal, waited s>= 100 ms:
1344          if ((r==0) || (errno != EINTR)) break;
1345        }
1346        if (kill(d->pid,0) == 0) // pid still exists
1347        {
1348          kill(d->pid,15);
1349          t.tv_sec=5; // <=5s
1350          t.tv_nsec=0;
1351          loop
1352          {
1353            // wait till signal or time rem:
1354            r = nanosleep(&t, &rem);
1355            t = rem;
1356            // child finished:
1357            if (si_waitpid(d->pid,NULL,WNOHANG) != 0) break;
1358            // other signal, waited s>=  5 s:
1359            if ((r==0) || (errno != EINTR)) break;
1360          }
1361          if (kill(d->pid,0) == 0)
1362          {
1363            kill(d->pid,9); // just to be sure
1364            si_waitpid(d->pid,NULL,0);
1365          }
1366        }
1367      }
1368      if (d->f_read!=NULL) { s_close(d->f_read);d->f_read=NULL;}
1369      if (d->f_write!=NULL) { fclose(d->f_write); d->f_write=NULL; }
1370      if ((strcmp(l->mode,"tcp")==0)
1371      || (strcmp(l->mode,"fork")==0))
1372      {
1373        link_list hh=ssiToBeClosed;
1374        if (hh!=NULL)
1375        {
1376          if (hh->l==l)
1377          {
1378             ssiToBeClosed=(link_list)hh->next;
1379             omFreeSize(hh,sizeof(link_struct));
1380          }
1381          else while(hh->next!=NULL)
1382          {
1383            link_list hhh=(link_list)hh->next;
1384            if (hhh->l==l)
1385            {
1386              hh->next=hhh->next;
1387              omFreeSize(hhh,sizeof(link_struct));
1388              break;
1389            }
1390            else
1391              hh=(link_list)hh->next;
1392          }
1393        }
1394      }
1395      omFreeSize((ADDRESS)d,(sizeof *d));
1396    }
1397    l->data=NULL;
1398  }
1399  return FALSE;
1400}
1401
1402//**************************************************************************/
1403leftv ssiRead1(si_link l)
1404{
1405  ssiInfo *d = (ssiInfo *)l->data;
1406  leftv res=(leftv)omAlloc0Bin(sleftv_bin);
1407  int t=0;
1408  t=s_readint(d->f_read);
1409  //Print("got type %d\n",t);
1410  switch(t)
1411  {
1412    case 1:res->rtyp=INT_CMD;
1413           res->data=(char *)(long)ssiReadInt(d->f_read);
1414           break;
1415    case 2:res->rtyp=STRING_CMD;
1416           res->data=(char *)ssiReadString(d);
1417           break;
1418    case 3:res->rtyp=NUMBER_CMD;
1419           if (d->r==NULL) goto no_ring;
1420           ssiCheckCurrRing(d->r);
1421           res->data=(char *)ssiReadNumber(d);
1422           break;
1423    case 4:res->rtyp=BIGINT_CMD;
1424           res->data=(char *)ssiReadBigInt(d);
1425           break;
1426    case 15:
1427    case 5:{
1428             d->r=ssiReadRing(d);
1429             if (errorreported) return NULL;
1430             res->data=(char*)d->r;
1431             if (d->r!=NULL) rIncRefCnt(d->r);
1432             res->rtyp=RING_CMD;
1433             if (t==15) // setring
1434             {
1435               if(ssiSetCurrRing(d->r)) { d->r=currRing; }
1436               omFreeBin(res,sleftv_bin);
1437               return ssiRead1(l);
1438             }
1439           }
1440           break;
1441    case 6:res->rtyp=POLY_CMD;
1442           if (d->r==NULL) goto no_ring;
1443           ssiCheckCurrRing(d->r);
1444           res->data=(char*)ssiReadPoly(d);
1445           break;
1446    case 7:res->rtyp=IDEAL_CMD;
1447           if (d->r==NULL) goto no_ring;
1448           ssiCheckCurrRing(d->r);
1449           res->data=(char*)ssiReadIdeal(d);
1450           break;
1451    case 8:res->rtyp=MATRIX_CMD;
1452           if (d->r==NULL) goto no_ring;
1453           ssiCheckCurrRing(d->r);
1454           res->data=(char*)ssiReadMatrix(d);
1455           break;
1456    case 9:res->rtyp=VECTOR_CMD;
1457           if (d->r==NULL) goto no_ring;
1458           ssiCheckCurrRing(d->r);
1459           res->data=(char*)ssiReadPoly(d);
1460           break;
1461    case 10:
1462    case 22:if (t==22) res->rtyp=SMATRIX_CMD;
1463           else        res->rtyp=MODUL_CMD;
1464           if (d->r==NULL) goto no_ring;
1465           ssiCheckCurrRing(d->r);
1466           {
1467             int rk=s_readint(d->f_read);
1468             ideal M=ssiReadIdeal(d);
1469             M->rank=rk;
1470             res->data=(char*)M;
1471           }
1472           break;
1473    case 11:
1474           {
1475             res->rtyp=COMMAND;
1476             res->data=ssiReadCommand(l);
1477             int nok=res->Eval();
1478             if (nok) WerrorS("error in eval");
1479             break;
1480           }
1481    case 12: /*DEF_CMD*/
1482           {
1483             res->rtyp=0;
1484             res->name=(char *)ssiReadString(d);
1485             int nok=res->Eval();
1486             if (nok) WerrorS("error in name lookup");
1487             break;
1488           }
1489    case 13: res->rtyp=PROC_CMD;
1490             res->data=ssiReadProc(d);
1491             break;
1492    case 14: res->rtyp=LIST_CMD;
1493             res->data=ssiReadList(l);
1494             break;
1495    case 16: res->rtyp=NONE; res->data=NULL;
1496             break;
1497    case 17: res->rtyp=INTVEC_CMD;
1498             res->data=ssiReadIntvec(d);
1499             break;
1500    case 18: res->rtyp=INTMAT_CMD;
1501             res->data=ssiReadIntmat(d);
1502             break;
1503    case 19: res->rtyp=BIGINTMAT_CMD;
1504             res->data=ssiReadBigintmat(d);
1505             break;
1506    case 20: ssiReadBlackbox(res,l);
1507             break;
1508    case 21: ssiReadAttrib(res,l);
1509             break;
1510    case 23: ssiReadRingProperties(l);
1511             return ssiRead1(l);
1512             break;
1513    // ------------
1514    case 98: // version
1515             {
1516                int n98_v,n98_m;
1517                BITSET n98_o1,n98_o2;
1518                n98_v=s_readint(d->f_read);
1519                n98_m=s_readint(d->f_read);
1520                n98_o1=s_readint(d->f_read);
1521                n98_o2=s_readint(d->f_read);
1522                if ((n98_v!=SSI_VERSION) ||(n98_m!=MAX_TOK))
1523                {
1524                  Print("incompatible versions of ssi: %d/%d vs %d/%d\n",
1525                                  SSI_VERSION,MAX_TOK,n98_v,n98_m);
1526                }
1527                #ifndef SING_NDEBUG
1528                if (TEST_OPT_DEBUG)
1529                  Print("// opening ssi-%d, MAX_TOK=%d\n",n98_v,n98_m);
1530                #endif
1531                si_opt_1=n98_o1;
1532                si_opt_2=n98_o2;
1533                omFreeBin(res,sleftv_bin);
1534                return ssiRead1(l);
1535             }
1536    case 99: omFreeBin(res,sleftv_bin); ssiClose(l); m2_end(0);
1537    case 0: if (s_iseof(d->f_read))
1538            {
1539              ssiClose(l);
1540            }
1541            res->rtyp=DEF_CMD;
1542            break;
1543    default: Werror("not implemented (t:%d)",t);
1544             omFreeBin(res,sleftv_bin);
1545             res=NULL;
1546             break;
1547  }
1548  // if currRing is required for the result, but lost
1549  // define "ssiRing%d" as currRing:
1550  if ((d->r!=NULL)
1551  && (currRing!=d->r)
1552  && (res->RingDependend()))
1553  {
1554    if(ssiSetCurrRing(d->r)) { d->r=currRing; }
1555  }
1556  return res;
1557no_ring: WerrorS("no ring");
1558  omFreeBin(res,sleftv_bin);
1559  return NULL;
1560}
1561//**************************************************************************/
1562BOOLEAN ssiSetRing(si_link l, ring r, BOOLEAN send)
1563{
1564  if(SI_LINK_W_OPEN_P(l)==0)
1565     if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE;
1566  ssiInfo *d = (ssiInfo *)l->data;
1567  if (d->r!=r)
1568  {
1569    if (send)
1570    {
1571      fputs("15 ",d->f_write);
1572      ssiWriteRing(d,r);
1573    }
1574    d->r=r;
1575  }
1576  if (currRing!=r) rChangeCurrRing(r);
1577  return FALSE;
1578}
1579//**************************************************************************/
1580
1581BOOLEAN ssiWrite(si_link l, leftv data)
1582{
1583  if(SI_LINK_W_OPEN_P(l)==0)
1584     if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE;
1585  ssiInfo *d = (ssiInfo *)l->data;
1586  d->level++;
1587  //FILE *fich=d->f;
1588  while (data!=NULL)
1589  {
1590    int tt=data->Typ();
1591    void *dd=data->Data();
1592    attr *aa=data->Attribute();
1593    if ((aa!=NULL) && ((*aa)!=NULL)) // n user attributes
1594    {
1595      attr a=*aa;
1596      int n=0;
1597      while(a!=NULL) { n++; a=a->next;}
1598      fprintf(d->f_write,"21 %d %d ",data->flag,n);
1599    }
1600    else if (data->flag!=0) // only "flag" attributes
1601    {
1602      fprintf(d->f_write,"21 %d 0 ",data->flag);
1603    }
1604    if ((dd==NULL) && (data->name!=NULL) && (tt==0)) tt=DEF_CMD;
1605      // return pure undefined names as def
1606
1607    switch(tt /*data->Typ()*/)
1608    {
1609          case 0: /*error*/
1610          case NONE/* nothing*/:fputs("16 ",d->f_write);
1611                          break;
1612          case STRING_CMD: fputs("2 ",d->f_write);
1613                           ssiWriteString(d,(char *)dd);
1614                           break;
1615          case INT_CMD: fputs("1 ",d->f_write);
1616                        ssiWriteInt(d,(int)(long)dd);
1617                        break;
1618          case BIGINT_CMD:fputs("4 ",d->f_write);
1619                        ssiWriteBigInt(d,(number)dd);
1620                        break;
1621          case NUMBER_CMD:
1622                          if (d->r!=currRing)
1623                          {
1624                            fputs("15 ",d->f_write);
1625                            ssiWriteRing(d,currRing);
1626                            if (d->level<=1) fputc('\n',d->f_write);
1627                          }
1628                          fputs("3 ",d->f_write);
1629                          ssiWriteNumber(d,(number)dd);
1630                        break;
1631          case RING_CMD:fputs("5 ",d->f_write);
1632                        ssiWriteRing(d,(ring)dd);
1633                        break;
1634          case BUCKET_CMD:
1635                        {
1636                          sBucket_pt b=(sBucket_pt)dd;
1637                          if (d->r!=sBucketGetRing(b))
1638                          {
1639                            fputs("15 ",d->f_write);
1640                            ssiWriteRing(d,sBucketGetRing(b));
1641                            if (d->level<=1) fputc('\n',d->f_write);
1642                          }
1643                          fputs("6 ",d->f_write);
1644                          ssiWritePoly(d,tt,sBucketPeek(b));
1645                          break;
1646                        }
1647          case POLY_CMD:
1648          case VECTOR_CMD:
1649                        if (d->r!=currRing)
1650                        {
1651                          fputs("15 ",d->f_write);
1652                          ssiWriteRing(d,currRing);
1653                          if (d->level<=1) fputc('\n',d->f_write);
1654                        }
1655                        if(tt==POLY_CMD) fputs("6 ",d->f_write);
1656                        else             fputs("9 ",d->f_write);
1657                        ssiWritePoly(d,tt,(poly)dd);
1658                        break;
1659          case IDEAL_CMD:
1660          case MODUL_CMD:
1661          case MATRIX_CMD:
1662          case SMATRIX_CMD:
1663                        if (d->r!=currRing)
1664                        {
1665                          fputs("15 ",d->f_write);
1666                          ssiWriteRing(d,currRing);
1667                          if (d->level<=1) fputc('\n',d->f_write);
1668                        }
1669                        if(tt==IDEAL_CMD)       fputs("7 ",d->f_write);
1670                        else if(tt==MATRIX_CMD) fputs("8 ",d->f_write);
1671                        else if(tt==SMATRIX_CMD) fputs("22 ",d->f_write);
1672                        else /* tt==MODUL_CMD*/
1673                        {
1674                          ideal M=(ideal)dd;
1675                          fprintf(d->f_write,"10 %d ",(int)M->rank);
1676                        }
1677                        ssiWriteIdeal(d,tt,(ideal)dd);
1678                        break;
1679          case COMMAND:
1680                   fputs("11 ",d->f_write);
1681                   ssiWriteCommand(l,(command)dd);
1682                   break;
1683          case DEF_CMD: /* not evaluated stuff in quotes */
1684                   fputs("12 ",d->f_write);
1685                   ssiWriteString(d,data->Name());
1686                   break;
1687          case PROC_CMD:
1688                   fputs("13 ",d->f_write);
1689                   ssiWriteProc(d,(procinfov)dd);
1690                   break;
1691          case LIST_CMD:
1692                   fputs("14 ",d->f_write);
1693                   ssiWriteList(l,(lists)dd);
1694                   break;
1695          case INTVEC_CMD:
1696                   fputs("17 ",d->f_write);
1697                   ssiWriteIntvec(d,(intvec *)dd);
1698                   break;
1699          case INTMAT_CMD:
1700                   fputs("18 ",d->f_write);
1701                   ssiWriteIntmat(d,(intvec *)dd);
1702                   break;
1703          case BIGINTMAT_CMD:
1704                   fputs("19 ",d->f_write);
1705                   ssiWriteBigintmat(d,(bigintmat *)dd);
1706                   break;
1707          default:
1708            if (tt>MAX_TOK)
1709            {
1710              blackbox *b=getBlackboxStuff(tt);
1711              fputs("20 ",d->f_write);
1712              b->blackbox_serialize(b,dd,l);
1713            }
1714            else
1715            {
1716              Werror("not implemented (t:%d, rtyp:%d)",tt, data->rtyp);
1717              d->level=0;
1718              return TRUE;
1719            }
1720            break;
1721    }
1722    if (d->level<=1) { fputc('\n',d->f_write); fflush(d->f_write); }
1723    data=data->next;
1724  }
1725  d->level--;
1726  return FALSE;
1727}
1728
1729BOOLEAN ssiGetDump(si_link l);
1730BOOLEAN ssiDump(si_link l);
1731
1732si_link_extension slInitSsiExtension(si_link_extension s)
1733{
1734  s->Open=ssiOpen;
1735  s->Close=ssiClose;
1736  s->Kill=ssiClose;
1737  s->Read=ssiRead1;
1738  s->Read2=(slRead2Proc)NULL;
1739  s->Write=ssiWrite;
1740  s->Dump=ssiDump;
1741  s->GetDump=ssiGetDump;
1742
1743  s->Status=slStatusSsi;
1744  s->SetRing=ssiSetRing;
1745  s->type="ssi";
1746  return s;
1747}
1748
1749const char* slStatusSsi(si_link l, const char* request)
1750{
1751  ssiInfo *d=(ssiInfo*)l->data;
1752  if (d==NULL) return "not open";
1753  if (((strcmp(l->mode,"fork")==0)
1754  ||(strcmp(l->mode,"tcp")==0)
1755  ||(strcmp(l->mode,"connect")==0))
1756  && (strcmp(request, "read") == 0))
1757  {
1758    fd_set  mask;
1759    struct timeval wt;
1760    if (s_isready(d->f_read)) return "ready";
1761    loop
1762    {
1763      /* Don't block. Return socket status immediately. */
1764      wt.tv_sec  = 0;
1765      wt.tv_usec = 0;
1766
1767      FD_ZERO(&mask);
1768      FD_SET(d->fd_read, &mask);
1769      //Print("test fd %d\n",d->fd_read);
1770    /* check with select: chars waiting: no -> not ready */
1771      switch (si_select(d->fd_read+1, &mask, NULL, NULL, &wt))
1772      {
1773        case 0: /* not ready */ return "not ready";
1774        case -1: /*error*/      return "error";
1775        case 1: /*ready ? */    break;
1776      }
1777    /* yes: read 1 char*/
1778    /* if \n, check again with select else ungetc(c), ready*/
1779      int c=s_getc(d->f_read);
1780      //Print("try c=%d\n",c);
1781      if (c== -1) return "eof"; /* eof or error */
1782      else if (isdigit(c))
1783      { s_ungetc(c,d->f_read); return "ready"; }
1784      else if (c>' ')
1785      {
1786        Werror("unknown char in ssiLink(%d)",c);
1787        return "error";
1788      }
1789      /* else: next char */
1790    }
1791  }
1792  else if (strcmp(request, "read") == 0)
1793  {
1794    if (SI_LINK_R_OPEN_P(l) && (!s_iseof(d->f_read)) && (s_isready(d->f_read))) return "ready";
1795    else return "not ready";
1796  }
1797  else if (strcmp(request, "write") == 0)
1798  {
1799    if (SI_LINK_W_OPEN_P(l)) return "ready";
1800    else return "not ready";
1801  }
1802  else return "unknown status request";
1803}
1804
1805int slStatusSsiL(lists L, int timeout)
1806{
1807// input: L: a list with links of type
1808//           ssi-connect, ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch.
1809//           Note: Not every entry in L must be set.
1810//        timeout: timeout for select in micro-seconds
1811//           or -1 for infinity
1812//           or 0 for polling
1813// returns: ERROR (via Werror): L has wrong elements or link not open
1814//           -2: select returns an error
1815//           -1: the read state of all links is eof
1816//           0:  timeout (or polling): none ready,
1817//           i>0: (at least) L[i] is ready
1818  si_link l;
1819  ssiInfo *d;
1820  int d_fd;
1821  fd_set  mask, fdmask;
1822  FD_ZERO(&fdmask);
1823  FD_ZERO(&mask);
1824  int max_fd=0; /* 1 + max fd in fd_set */
1825
1826  /* timeout */
1827  struct timeval wt;
1828  struct timeval *wt_ptr=&wt;
1829  int startingtime = getRTimer()/TIMER_RESOLUTION;  // in seconds
1830  if (timeout== -1)
1831  {
1832    wt_ptr=NULL;
1833  }
1834  else
1835  {
1836    wt.tv_sec  = timeout / 1000000;
1837    wt.tv_usec = timeout % 1000000;
1838  }
1839
1840  /* auxiliary variables */
1841  int i;
1842  int j;
1843  int k;
1844  int s;
1845  char fdmaskempty;
1846
1847  /* check the links and fill in fdmask */
1848  /* check ssi links for ungetc_buf */
1849  for(i=L->nr; i>=0; i--)
1850  {
1851    if (L->m[i].Typ()!=DEF_CMD)
1852    {
1853      if (L->m[i].Typ()!=LINK_CMD)
1854      { WerrorS("all elements must be of type link"); return -2;}
1855      l=(si_link)L->m[i].Data();
1856      if(SI_LINK_OPEN_P(l)==0)
1857      { WerrorS("all links must be open"); return -2;}
1858      if (((strcmp(l->m->type,"ssi")!=0) && (strcmp(l->m->type,"MPtcp")!=0))
1859      || ((strcmp(l->mode,"fork")!=0) && (strcmp(l->mode,"tcp")!=0)
1860        && (strcmp(l->mode,"launch")!=0) && (strcmp(l->mode,"connect")!=0)))
1861      {
1862        WerrorS("all links must be of type ssi:fork, ssi:tcp, ssi:connect");
1863        return -2;
1864      }
1865      if (strcmp(l->m->type,"ssi")==0)
1866      {
1867        d=(ssiInfo*)l->data;
1868        d_fd=d->fd_read;
1869        if (!s_isready(d->f_read))
1870        {
1871          FD_SET(d_fd, &fdmask);
1872          if (d_fd > max_fd) max_fd=d_fd;
1873        }
1874        else
1875          return i+1;
1876      }
1877      else
1878      {
1879        Werror("wrong link type >>%s<<",l->m->type);
1880        return -2;
1881      }
1882    }
1883  }
1884  max_fd++;
1885
1886do_select:
1887  /* copy fdmask to mask */
1888  FD_ZERO(&mask);
1889  for(k = 0; k < max_fd; k++)
1890  {
1891    if(FD_ISSET(k, &fdmask))
1892    {
1893      FD_SET(k, &mask);
1894    }
1895  }
1896
1897  /* check with select: chars waiting: no -> not ready */
1898  s = si_select(max_fd, &mask, NULL, NULL, wt_ptr);
1899  if (s==-1)
1900  {
1901    WerrorS("error in select call");
1902    return -2; /*error*/
1903  }
1904  if (s==0)
1905  {
1906    return 0; /*poll: not ready */
1907  }
1908  else /* s>0, at least one ready  (the number of fd which are ready is s)*/
1909  {
1910    j=0;
1911    while (j<=max_fd) { if (FD_ISSET(j,&mask)) break; j++; }
1912    for(i=L->nr; i>=0; i--)
1913    {
1914      if (L->m[i].rtyp==LINK_CMD)
1915      {
1916        l=(si_link)L->m[i].Data();
1917        if (strcmp(l->m->type,"ssi")==0)
1918        {
1919          d=(ssiInfo*)l->data;
1920          d_fd=d->fd_read;
1921          if(j==d_fd) break;
1922        }
1923        else
1924        {
1925          Werror("wrong link type >>%s<<",l->m->type);
1926          return -2;
1927        }
1928      }
1929    }
1930    // only ssi links:
1931    loop
1932    {
1933      /* yes: read 1 char*/
1934      /* if \n, check again with select else ungetc(c), ready*/
1935      /* setting: d: current ssiInfo, j current fd, i current entry in L*/
1936      int c=s_getc(d->f_read);
1937      //Print("try c=%d\n",c);
1938      if (c== -1) /* eof */
1939      {
1940        FD_CLR(j,&fdmask);
1941        fdmaskempty = 1;
1942        for(k = 0; k < max_fd; k++)
1943        {
1944          if(FD_ISSET(k, &fdmask))
1945          {
1946            fdmaskempty = 0;
1947            break;
1948          }
1949        }
1950        if(fdmaskempty)
1951        {
1952          return -1;
1953        }
1954        if(timeout != -1)
1955        {
1956          timeout = si_max(0,
1957             timeout - 1000000*(getRTimer()/TIMER_RESOLUTION - startingtime));
1958          wt.tv_sec  = timeout / 1000000;
1959          wt.tv_usec = (timeout % 1000000);
1960        }
1961        goto do_select;
1962      }
1963
1964      else if (isdigit(c))
1965      { s_ungetc(c,d->f_read); return i+1; }
1966      else if (c>' ')
1967      {
1968        Werror("unknown char in ssiLink(%d)",c);
1969        return -2;
1970      }
1971      /* else: next char */
1972      goto do_select;
1973    }
1974  }
1975}
1976
1977int ssiBatch(const char *host, const char * port)
1978/* return 0 on success, >0 else*/
1979{
1980  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1981  char *buf=(char*)omAlloc(256);
1982  sprintf(buf,"ssi:connect %s:%s",host,port);
1983  slInit(l, buf);
1984  omFreeSize(buf,256);
1985  if (slOpen(l,SI_LINK_OPEN,NULL)) return 1;
1986  SI_LINK_SET_RW_OPEN_P(l);
1987
1988  idhdl id = enterid("link_ll", 0, LINK_CMD, &IDROOT, FALSE);
1989  IDLINK(id) = l;
1990
1991  loop
1992  {
1993    leftv h=ssiRead1(l); /*contains an exit.... */
1994    if (feErrors != NULL && *feErrors != '\0')
1995    {
1996      // handle errors:
1997      PrintS(feErrors); /* currently quite simple */
1998      *feErrors = '\0';
1999    }
2000    ssiWrite(l,h);
2001    h->CleanUp();
2002    omFreeBin(h, sleftv_bin);
2003  }
2004  /* never reached*/
2005  exit(0);
2006}
2007
2008STATIC_VAR int ssiReserved_P=0;
2009STATIC_VAR int ssiReserved_sockfd;
2010STATIC_VAR struct sockaddr_in ssiResverd_serv_addr;
2011STATIC_VAR int  ssiReserved_Clients;
2012int ssiReservePort(int clients)
2013{
2014  if (ssiReserved_P!=0)
2015  {
2016    WerrorS("ERROR already a reverved port requested");
2017    return 0;
2018  }
2019  int portno;
2020  ssiReserved_sockfd = socket(AF_INET, SOCK_STREAM, 0);
2021  if(ssiReserved_sockfd < 0)
2022  {
2023    WerrorS("ERROR opening socket");
2024    return 0;
2025  }
2026  memset((char *) &ssiResverd_serv_addr,0, sizeof(ssiResverd_serv_addr));
2027  portno = 1025;
2028  ssiResverd_serv_addr.sin_family = AF_INET;
2029  ssiResverd_serv_addr.sin_addr.s_addr = INADDR_ANY;
2030  do
2031  {
2032    portno++;
2033    ssiResverd_serv_addr.sin_port = htons(portno);
2034    if(portno > 50000)
2035    {
2036      WerrorS("ERROR on binding (no free port available?)");
2037      return 0;
2038    }
2039  }
2040  while(bind(ssiReserved_sockfd, (struct sockaddr *) &ssiResverd_serv_addr, sizeof(ssiResverd_serv_addr)) < 0);
2041  ssiReserved_P=portno;
2042  listen(ssiReserved_sockfd,clients);
2043  ssiReserved_Clients=clients;
2044  return portno;
2045}
2046
2047EXTERN_VAR si_link_extension si_link_root;
2048si_link ssiCommandLink()
2049{
2050  if (ssiReserved_P==0)
2051  {
2052    WerrorS("ERROR no reverved port requested");
2053    return NULL;
2054  }
2055  struct sockaddr_in cli_addr;
2056  int clilen = sizeof(cli_addr);
2057  int newsockfd = si_accept(ssiReserved_sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
2058  if(newsockfd < 0)
2059  {
2060    Werror("ERROR on accept (errno=%d)",errno);
2061    return NULL;
2062  }
2063  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
2064  si_link_extension s = si_link_root;
2065  si_link_extension prev = s;
2066  while (strcmp(s->type, "ssi") != 0)
2067  {
2068    if (s->next == NULL)
2069    {
2070      prev = s;
2071      s = NULL;
2072      break;
2073    }
2074    else
2075    {
2076      s = s->next;
2077    }
2078  }
2079  if (s != NULL)
2080    l->m = s;
2081  else
2082  {
2083    si_link_extension ns = (si_link_extension)omAlloc0Bin(s_si_link_extension_bin);
2084    prev->next=slInitSsiExtension(ns);
2085    l->m = prev->next;
2086  }
2087  l->name=omStrDup("");
2088  l->mode=omStrDup("tcp");
2089  l->ref=1;
2090  ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
2091  l->data=d;
2092  d->fd_read = newsockfd;
2093  d->fd_write = newsockfd;
2094  d->f_read = s_open(newsockfd);
2095  d->f_write = fdopen(newsockfd, "w");
2096  SI_LINK_SET_RW_OPEN_P(l);
2097  ssiReserved_Clients--;
2098  if (ssiReserved_Clients<=0)
2099  {
2100    ssiReserved_P=0;
2101    si_close(ssiReserved_sockfd);
2102  }
2103  return l;
2104}
2105/*---------------------------------------------------------------------*/
2106/**
2107 * @brief additional default signal handler
2108
2109  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
2110  // so use this nice routine here:
2111  //  SuSe 9.x reports -1 always
2112  //  Redhat 9.x/FC x reports sometimes -1
2113  // see also: hpux_system
2114  // also needed by getrusage (timer etc.)
2115
2116 @param[in] sig
2117**/
2118/*---------------------------------------------------------------------*/
2119void sig_chld_hdl(int)
2120{
2121  pid_t kidpid;
2122  int status;
2123
2124  loop
2125  {
2126    kidpid = si_waitpid(-1, &status, WNOHANG);
2127    if (kidpid==-1)
2128    {
2129      /* continue on interruption (EINTR): */
2130      if (errno == EINTR) continue;
2131      /* break on anything else (EINVAL or ECHILD according to manpage): */
2132      break;
2133    }
2134    else if (kidpid==0) break; /* no more children to process, so break */
2135
2136    //printf("Child %ld terminated\n", kidpid);
2137    link_list hh=ssiToBeClosed;
2138    while((hh!=NULL)&&(ssiToBeClosed_inactive))
2139    {
2140      if((hh->l!=NULL) && (hh->l->m->Open==ssiOpen))
2141      {
2142        ssiInfo *d = (ssiInfo *)hh->l->data;
2143        if(d->pid==kidpid)
2144        {
2145          if(ssiToBeClosed_inactive)
2146          {
2147            ssiToBeClosed_inactive=FALSE;
2148            slClose(hh->l);
2149            ssiToBeClosed_inactive=TRUE;
2150            break;
2151          }
2152          else break;
2153        }
2154        else hh=(link_list)hh->next;
2155      }
2156      else hh=(link_list)hh->next;
2157    }
2158  }
2159}
2160
2161static BOOLEAN DumpSsiIdhdl(si_link l, idhdl h)
2162{
2163  int type_id = IDTYP(h);
2164
2165  // C-proc not to be dumped, also LIB-proc not
2166  if (type_id == PROC_CMD)
2167  {
2168    if (IDPROC(h)->language == LANG_C) return FALSE;
2169    if (IDPROC(h)->libname != NULL) return FALSE;
2170  }
2171  // do not dump links
2172  if (type_id == LINK_CMD) return FALSE;
2173
2174  // do not dump ssi internal rings: ssiRing*
2175  if ((type_id == RING_CMD) && (strncmp(IDID(h),"ssiRing",7)==0))
2176    return FALSE;
2177
2178  // do not dump default cring:
2179  if (type_id == CRING_CMD)
2180  {
2181    if (strcmp(IDID(h),"ZZ")==0) return FALSE;
2182    if (strcmp(IDID(h),"QQ")==0) return FALSE;
2183    #ifdef SINGULAR_4_2
2184    if (strcmp(IDID(h),"AE")==0) return FALSE;
2185    if (strcmp(IDID(h),"QAE")==0) return FALSE;
2186    #endif
2187  }
2188
2189  command D=(command)omAlloc0(sizeof(*D));
2190  sleftv tmp;
2191  memset(&tmp,0,sizeof(tmp));
2192  tmp.rtyp=COMMAND;
2193  tmp.data=D;
2194
2195  if (type_id == PACKAGE_CMD)
2196  {
2197    // do not dump Top, Standard
2198    if ((strcmp(IDID(h), "Top") == 0)
2199    || (strcmp(IDID(h), "Standard") == 0))
2200    {
2201      omFreeSize(D,sizeof(*D));
2202      return FALSE;
2203    }
2204    package p=(package)IDDATA(h);
2205    // dump Singular-packages as LIB("...");
2206    if (p->language==LANG_SINGULAR)
2207    {
2208      D->op=LOAD_CMD;
2209      D->argc=2;
2210      D->arg1.rtyp=STRING_CMD;
2211      D->arg1.data=p->libname;
2212      D->arg2.rtyp=STRING_CMD;
2213      D->arg2.data=(char*)"with";
2214      ssiWrite(l,&tmp);
2215      omFreeSize(D,sizeof(*D));
2216      return FALSE;
2217    }
2218    // dump Singular-packages as load("...");
2219    else if (p->language==LANG_C)
2220    {
2221      D->op=LOAD_CMD;
2222      D->argc=1;
2223      D->arg1.rtyp=STRING_CMD;
2224      D->arg1.data=p->libname;
2225      ssiWrite(l,&tmp);
2226      omFreeSize(D,sizeof(*D));
2227      return FALSE;
2228    }
2229  }
2230
2231  // put type and name
2232  //Print("generic dump:%s,%s\n",IDID(h),Tok2Cmdname(IDTYP(h)));
2233  D->op='=';
2234  D->argc=2;
2235  D->arg1.rtyp=DEF_CMD;
2236  D->arg1.name=IDID(h);
2237  D->arg2.rtyp=IDTYP(h);
2238  D->arg2.data=IDDATA(h);
2239  ssiWrite(l,&tmp);
2240  omFreeSize(D,sizeof(*D));
2241  return FALSE;
2242}
2243static BOOLEAN ssiDumpIter(si_link l, idhdl h)
2244{
2245  if (h == NULL) return FALSE;
2246
2247  if (ssiDumpIter(l, IDNEXT(h))) return TRUE;
2248
2249  // need to set the ring before writing it, otherwise we get in
2250  // trouble with minpoly
2251  if (IDTYP(h) == RING_CMD)
2252    rSetHdl(h);
2253
2254  if (DumpSsiIdhdl(l, h)) return TRUE;
2255
2256  // do not dump ssi internal rings: ssiRing*
2257  // but dump objects of all other rings
2258  if ((IDTYP(h) == RING_CMD)
2259  && (strncmp(IDID(h),"ssiRing",7)!=0))
2260    return ssiDumpIter(l, IDRING(h)->idroot);
2261  else
2262    return FALSE;
2263}
2264BOOLEAN ssiDump(si_link l)
2265{
2266  idhdl h = IDROOT, rh = currRingHdl;
2267  BOOLEAN status = ssiDumpIter(l, h);
2268
2269  //if (! status ) status = DumpAsciiMaps(fd, h, NULL);
2270
2271  if (currRingHdl != rh) rSetHdl(rh);
2272  //fprintf(fd, "option(set, intvec(%d, %d));\n", si_opt_1, si_opt_2);
2273
2274  return status;
2275}
2276BOOLEAN ssiGetDump(si_link l)
2277{
2278  ssiInfo *d=(ssiInfo*)l->data;
2279  loop
2280  {
2281    if (!SI_LINK_OPEN_P(l)) break;
2282    if (s_iseof(d->f_read)) break;
2283    leftv h=ssiRead1(l); /*contains an exit.... */
2284    if (feErrors != NULL && *feErrors != '\0')
2285    {
2286      // handle errors:
2287      PrintS(feErrors); /* currently quite simple */
2288      return TRUE;
2289      *feErrors = '\0';
2290    }
2291    h->CleanUp();
2292    omFreeBin(h, sleftv_bin);
2293  }
2294  return FALSE;
2295}
2296// ----------------------------------------------------------------
2297// format
2298// 1 int %d
2299// 2 string <len> %s
2300// 3 number
2301// 4 bigint 4 %d or 3 <mpz_t>
2302// 5 ring
2303// 6 poly
2304// 7 ideal
2305// 8 matrix
2306// 9 vector
2307// 10 module
2308// 11 command
2309// 12 def <len> %s
2310// 13 proc <len> %s
2311// 14 list %d <elem1> ....
2312// 15 setring .......
2313// 16 nothing
2314// 17 intvec <len> ...
2315// 18 intmat
2316// 19 bigintmat <r> <c> ...
2317// 20 blackbox <name> 1 <len> ...
2318// 21 attrib <bit-attrib> <len> <a-name1> <val1>... <data>
2319// 22 smatrix
2320// 23 0 <log(bitmask)> ring properties: max.exp.
2321// 23 1 <log(bitmask)> <r->IsLPRing> ring properties:LPRing
2322// 23 2 <matrix C> <matrix D> ring properties: PLuralRing
2323//
2324// 98: verify version: <ssi-version> <MAX_TOK> <OPT1> <OPT2>
2325// 99: quit Singular
Note: See TracBrowser for help on using the repository browser.