source: git/Singular/links/ssiLink.cc @ 97c955

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