source: git/Singular/links/ssiLink.cc @ b8ad3a

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