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