source: git/Singular/links/ssiLink.cc @ 72a01e

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