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

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