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

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