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

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