source: git/Singular/links/ssiLink.cc @ 2fa80a

spielwiese
Last change on this file since 2fa80a was d600e18, checked in by Andreas Steenpass <steenpass@…>, 10 years ago
chg: release acquired semaphores before shutdown (cherry picked from commit 0f27f90c69fc9952c3df5edb6dff0b57fd8ff826) Signed-off-by: Andreas Steenpass <steenpass@mathematik.uni-kl.de> Conflicts: Singular/links/semaphore.c Singular/misc_ip.cc
  • Property mode set to 100644
File size: 50.3 KB
Line 
1/****************************************
2 * Computer Algebra System SINGULAR     *
3 ****************************************/
4/***************************************************************
5 * File:    ssiLink.h
6 *  Purpose: declaration of sl_link routines for ssi
7 ***************************************************************/
8#include <stdio.h>
9#include <fcntl.h>
10#include <errno.h>
11#include <unistd.h>
12#include <sys/types.h>
13#include <signal.h>
14#include <sys/types.h>          /* for portability */
15#include <sys/select.h>
16#include <sys/socket.h>
17#include <netinet/in.h>
18#include <ctype.h>   /*for isdigit*/
19#include <netdb.h>
20#include <sys/wait.h>
21#include <time.h>
22
23#include <kernel/mod2.h>
24#include <Singular/si_signals.h>
25// #include "mod2.h"
26
27#include <Singular/tok.h>
28#include <Singular/ipid.h>
29#include <Singular/ipshell.h>
30#include <omalloc/omalloc.h>
31#include <libpolys/polys/monomials/ring.h>
32#include <libpolys/polys/matpol.h>
33#include <libpolys/polys/simpleideals.h>
34#include <libpolys/polys/monomials/p_polys.h>
35#include <libpolys/coeffs/longrat.h>
36#include <libpolys/misc/intvec.h>
37#include <libpolys/coeffs/bigintmat.h>
38#include <libpolys/misc/options.h>
39#include <kernel/timer.h>
40#include <Singular/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#ifdef HAVE_SIMPLEIPC
808          memset(sem_acquired, 0, SIPC_MAX_SEMAPHORES*sizeof(sem_acquired[0]));
809#endif   // HAVE_SIMPLEIPC
810          si_close(pc[1]); si_close(cp[0]);
811          d->f_write=fdopen(cp[1],"w");
812          d->f_read=s_open(pc[0]);
813          d->fd_read=pc[0];
814          d->fd_write=cp[1];
815          l->data=d;
816          omFree(l->mode);
817          l->mode = omStrDup(mode);
818          singular_in_batchmode=TRUE;
819          SI_LINK_SET_RW_OPEN_P(l);
820          //myynest=0;
821          fe_fgets_stdin=fe_fgets_dummy;
822          if ((u!=NULL)&&(u->rtyp==IDHDL))
823          {
824            idhdl h=(idhdl)u->data;
825            h->lev=0;
826          }
827          loop
828          {
829            leftv h=ssiRead1(l); /*contains an exit.... */
830            if (feErrors != NULL && *feErrors != '\0')
831            {
832              // handle errors:
833              PrintS(feErrors); /* currently quite simple */
834              *feErrors = '\0';
835            }
836            ssiWrite(l,h);
837            h->CleanUp();
838            omFreeBin(h, sleftv_bin);
839          }
840          /* never reached*/
841        }
842        else if (pid>0) /*fork: parent*/
843        {
844          d->pid=pid;
845          si_close(pc[0]); si_close(cp[1]);
846          d->f_write=fdopen(pc[1],"w");
847          d->f_read=s_open(cp[0]);
848          d->fd_read=cp[0];
849          d->fd_write=pc[1];
850          SI_LINK_SET_RW_OPEN_P(l);
851          d->send_quit_at_exit=1;
852        }
853        else
854        {
855          Werror("fork failed (%d)",errno);
856          l->data=NULL;
857          omFree(d);
858          return TRUE;
859        }
860      }
861      // ---------------------------------------------------------------------
862      else if (strcmp(mode,"tcp")==0)
863      {
864        int sockfd, newsockfd, portno, clilen;
865        struct sockaddr_in serv_addr, cli_addr;
866        int n;
867        sockfd = socket(AF_INET, SOCK_STREAM, 0);
868        if(sockfd < 0)
869        {
870          WerrorS("ERROR opening socket");
871          l->data=NULL;
872          omFree(d);
873          return TRUE;
874        }
875        memset((char *) &serv_addr,0, sizeof(serv_addr));
876        portno = 1025;
877        serv_addr.sin_family = AF_INET;
878        serv_addr.sin_addr.s_addr = INADDR_ANY;
879        do
880        {
881          portno++;
882          serv_addr.sin_port = htons(portno);
883          if(portno > 50000)
884          {
885            WerrorS("ERROR on binding (no free port available?)");
886            l->data=NULL;
887            omFree(d);
888            return TRUE;
889          }
890        }
891        while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
892        Print("waiting on port %d\n", portno);mflush();
893        listen(sockfd,1);
894        newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
895        if(newsockfd < 0)
896        {
897          WerrorS("ERROR on accept");
898          l->data=NULL;
899          omFree(d);
900          return TRUE;
901        }
902        PrintS("client accepted\n");
903        d->fd_read = newsockfd;
904        d->fd_write = newsockfd;
905        d->f_read = s_open(newsockfd);
906        d->f_write = fdopen(newsockfd, "w");
907        SI_LINK_SET_RW_OPEN_P(l);
908        si_close(sockfd);
909      }
910      // no ssi-Link on stdin or stdout
911      else
912      {
913        Werror("invalid mode >>%s<< for ssi",mode);
914        l->data=NULL;
915        omFree(d);
916        return TRUE;
917      }
918    }
919    // =========================================================================
920    else /*l->name=NULL*/
921    {
922      // tcp mode
923      if(strcmp(mode,"tcp")==0)
924      {
925        int sockfd, newsockfd, portno, clilen;
926        struct sockaddr_in serv_addr, cli_addr;
927        int n;
928        sockfd = socket(AF_INET, SOCK_STREAM, 0);
929        if(sockfd < 0)
930        {
931          WerrorS("ERROR opening socket");
932          l->data=NULL;
933          omFree(d);
934          return TRUE;
935        }
936        memset((char *) &serv_addr,0, sizeof(serv_addr));
937        portno = 1025;
938        serv_addr.sin_family = AF_INET;
939        serv_addr.sin_addr.s_addr = INADDR_ANY;
940        do
941        {
942          portno++;
943          serv_addr.sin_port = htons(portno);
944          if(portno > 50000)
945          {
946            WerrorS("ERROR on binding (no free port available?)");
947            l->data=NULL;
948            return TRUE;
949          }
950        }
951        while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
952        //Print("waiting on port %d\n", portno);mflush();
953        listen(sockfd,1);
954        char* cli_host = (char*)omAlloc(256);
955        char* path = (char*)omAlloc(1024);
956        int r = si_sscanf(l->name,"%255[^:]:%s",cli_host,path);
957        if(r == 0)
958        {
959          WerrorS("ERROR: no host specified");
960          l->data=NULL;
961          omFree(d);
962          omFree(path);
963          omFree(cli_host);
964          return TRUE;
965        }
966        else if(r == 1)
967        {
968          WarnS("program not specified, using /usr/local/bin/Singular");
969          strcpy(path,"/usr/local/bin/Singular");
970        }
971        char* ssh_command = (char*)omAlloc(256);
972        char* ser_host = (char*)omAlloc(64);
973        gethostname(ser_host,64);
974        sprintf(ssh_command,"ssh %s %s -q --batch --link=ssi --MPhost=%s --MPport=%d &",cli_host,path,ser_host,portno);
975        //Print("client on %s started:%s\n",cli_host,path);
976        omFree(path);
977        omFree(cli_host);
978        if (TEST_OPT_PROT) { Print("running >>%s<<\n",ssh_command); }
979        system(ssh_command);
980        omFree(ssh_command);
981        omFree(ser_host);
982        clilen = sizeof(cli_addr);
983        newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
984        if(newsockfd < 0)
985        {
986          WerrorS("ERROR on accept");
987          l->data=NULL;
988          omFree(d);
989          return TRUE;
990        }
991        //PrintS("client accepted\n");
992        d->fd_read = newsockfd;
993        d->fd_write = newsockfd;
994        d->f_read = s_open(newsockfd);
995        d->f_write = fdopen(newsockfd, "w");
996        si_close(sockfd);
997        SI_LINK_SET_RW_OPEN_P(l);
998        d->send_quit_at_exit=1;
999        link_list newlink=(link_list)omAlloc(sizeof(link_struct));
1000        newlink->u=u;
1001        newlink->l=l;
1002        newlink->next=(void *)ssiToBeClosed;
1003        ssiToBeClosed=newlink;
1004        fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2);
1005      }
1006      // ----------------------------------------------------------------------
1007      else if(strcmp(mode,"connect")==0)
1008      {
1009        char* host = (char*)omAlloc(256);
1010        int sockfd, portno, n;
1011        struct sockaddr_in serv_addr;
1012        struct hostent *server;
1013
1014        si_sscanf(l->name,"%255[^:]:%d",host,&portno);
1015        //Print("connect to host %s, port %d\n",host,portno);mflush();
1016        if (portno!=0)
1017        {
1018          sockfd = socket(AF_INET, SOCK_STREAM, 0);
1019          if (sockfd < 0) { WerrorS("ERROR opening socket"); return TRUE; }
1020          server = gethostbyname(host);
1021          if (server == NULL) {  WerrorS("ERROR, no such host");  return TRUE; }
1022          memset((char *) &serv_addr, 0, sizeof(serv_addr));
1023          serv_addr.sin_family = AF_INET;
1024          memcpy((char *)&serv_addr.sin_addr.s_addr,
1025                (char *)server->h_addr,
1026                server->h_length);
1027          serv_addr.sin_port = htons(portno);
1028          if (si_connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
1029          { Werror("ERROR connecting(errno=%d)",errno); return TRUE; }
1030          //PrintS("connected\n");mflush();
1031          d->f_read=s_open(sockfd);
1032          d->fd_read=sockfd;
1033          d->f_write=fdopen(sockfd,"w");
1034          d->fd_write=sockfd;
1035          SI_LINK_SET_RW_OPEN_P(l);
1036          omFree(host);
1037        }
1038        else
1039        {
1040          l->data=NULL;
1041          omFree(d);
1042          return TRUE;
1043        }
1044      }
1045      // ======================================================================
1046      else
1047      {
1048        // normal link to a file
1049        FILE *outfile;
1050        char *filename=l->name;
1051
1052        if(filename[0]=='>')
1053        {
1054          if (filename[1]=='>')
1055          {
1056            filename+=2;
1057            mode = "a";
1058          }
1059          else
1060          {
1061            filename++;
1062            mode="w";
1063          }
1064        }
1065        outfile=myfopen(filename,mode);
1066        if (outfile!=NULL)
1067        {
1068          if (strcmp(l->mode,"r")==0)
1069          {
1070            fclose(outfile);
1071            d->f_read=s_open_by_name(filename);
1072          }
1073          else
1074          {
1075            d->f_write = outfile;
1076            fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2);
1077          }
1078        }
1079        else
1080        {
1081          omFree(d);
1082          l->data=NULL;
1083          return TRUE;
1084        }
1085      }
1086    }
1087  }
1088
1089  return FALSE;
1090}
1091
1092//**************************************************************************/
1093BOOLEAN ssiPrepClose(si_link l)
1094{
1095  if (l!=NULL)
1096  {
1097    ssiInfo *d = (ssiInfo *)l->data;
1098    if (d!=NULL)
1099    {
1100      if (d->send_quit_at_exit)
1101      {
1102        fputs("99\n",d->f_write);
1103        fflush(d->f_write);
1104      }
1105      d->quit_sent=1;
1106    }
1107  }
1108  return FALSE;
1109}
1110
1111BOOLEAN ssiClose(si_link l)
1112{
1113  if (l!=NULL)
1114  {
1115    SI_LINK_SET_CLOSE_P(l);
1116    ssiInfo *d = (ssiInfo *)l->data;
1117    if (d!=NULL)
1118    {
1119      if ((d->send_quit_at_exit)
1120      && (d->quit_sent==0))
1121      {
1122        fputs("99\n",d->f_write);
1123        fflush(d->f_write);
1124      }
1125      if (d->r!=NULL) rKill(d->r);
1126      if ((d->pid!=0)
1127      && (si_waitpid(d->pid,NULL,WNOHANG)==0))
1128      {
1129        struct timespec t;
1130        t.tv_sec=0;
1131        t.tv_nsec=50000000; // <=50 ms
1132        int r=si_nanosleep(&t,NULL);
1133        if((r==0) && (si_waitpid(d->pid,NULL,WNOHANG)==0))
1134        {
1135          kill(d->pid,15);
1136          t.tv_sec=0;
1137          t.tv_nsec=10000000; // <=10 ms
1138          r=si_nanosleep(&t,NULL);
1139          if((r==0)&&(si_waitpid(d->pid,NULL,WNOHANG)==0))
1140          {
1141            kill(d->pid,9); // just to be sure
1142            si_waitpid(d->pid,NULL,0);
1143          }
1144        }
1145      }
1146      if (d->f_read!=NULL) s_close(d->f_read);
1147      if (d->f_read!=NULL) s_free(d->f_read);
1148      if (d->f_write!=NULL) fclose(d->f_write);
1149      if ((strcmp(l->mode,"tcp")==0)
1150      || (strcmp(l->mode,"fork")==0))
1151      {
1152        link_list hh=ssiToBeClosed;
1153        if (hh!=NULL)
1154        {
1155          if (hh->l==l)
1156          {
1157             ssiToBeClosed=(link_list)hh->next;
1158             omFreeSize(hh,sizeof(link_struct));
1159          }
1160          else while(hh->next!=NULL)
1161          {
1162            link_list hhh=(link_list)hh->next;
1163            if (hhh->l==l)
1164            {
1165              hh->next=hhh->next;
1166              omFreeSize(hhh,sizeof(link_struct));
1167              break;
1168            }
1169            else
1170              hh=(link_list)hh->next;
1171          }
1172        }
1173      }
1174      omFreeSize((ADDRESS)d,(sizeof *d));
1175    }
1176    l->data=NULL;
1177  }
1178  return FALSE;
1179}
1180
1181//**************************************************************************/
1182leftv ssiRead1(si_link l)
1183{
1184  ssiInfo *d = (ssiInfo *)l->data;
1185  leftv res=(leftv)omAlloc0(sizeof(sleftv));
1186  int t=0;
1187  t=s_readint(d->f_read);
1188  //Print("got type %d\n",t);
1189  switch(t)
1190  {
1191    case 1:res->rtyp=INT_CMD;
1192           res->data=(char *)(long)ssiReadInt(d->f_read);
1193           break;
1194    case 2:res->rtyp=STRING_CMD;
1195           res->data=(char *)ssiReadString(d);
1196           break;
1197    case 3:res->rtyp=NUMBER_CMD;
1198           res->data=(char *)ssiReadNumber(d);
1199           break;
1200    case 4:res->rtyp=BIGINT_CMD;
1201           res->data=(char *)ssiReadBigInt(d);
1202           break;
1203    case 15:
1204    case 5:{
1205             d->r=ssiReadRing(d);
1206             res->rtyp=RING_CMD;
1207             res->data=(char*)d->r;
1208             // we are in the top-level, so set the basering to d->r:
1209             if (d->r!=NULL)
1210             {
1211               d->r->ref++;
1212               ssiSetCurrRing(d->r);
1213             }
1214             if (t==15) return ssiRead1(l);
1215           }
1216           break;
1217    case 6:res->rtyp=POLY_CMD;
1218           if (d->r==NULL) goto no_ring;
1219           res->data=(char*)ssiReadPoly(d);
1220           break;
1221    case 7:res->rtyp=IDEAL_CMD;
1222           if (d->r==NULL) goto no_ring;
1223           res->data=(char*)ssiReadIdeal(d);
1224           break;
1225    case 8:res->rtyp=MATRIX_CMD;
1226           if (d->r==NULL) goto no_ring;
1227           res->data=(char*)ssiReadMatrix(d);
1228           break;
1229    case 9:res->rtyp=VECTOR_CMD;
1230           if (d->r==NULL) goto no_ring;
1231           res->data=(char*)ssiReadPoly(d);
1232           break;
1233    case 10:res->rtyp=MODUL_CMD;
1234           if (d->r==NULL) goto no_ring;
1235           res->data=(char*)ssiReadIdeal(d);
1236           break;
1237    case 11:
1238           {
1239             res->rtyp=COMMAND;
1240             res->data=ssiReadCommand(l);
1241             int nok=res->Eval();
1242             if (nok) WerrorS("error in eval");
1243             break;
1244           }
1245    case 12: /*DEF_CMD*/
1246           {
1247             res->rtyp=0;
1248             res->name=(char *)ssiReadString(d);
1249             int nok=res->Eval();
1250             if (nok) WerrorS("error in name lookup");
1251             break;
1252           }
1253    case 13: res->rtyp=PROC_CMD;
1254             res->data=ssiReadProc(d);
1255             break;
1256    case 14: res->rtyp=LIST_CMD;
1257             res->data=ssiReadList(l);
1258             break;
1259    case 16: res->rtyp=NONE; res->data=NULL;
1260             break;
1261    case 17: res->rtyp=INTVEC_CMD;
1262             res->data=ssiReadIntvec(d);
1263             break;
1264    case 18: res->rtyp=INTMAT_CMD;
1265             res->data=ssiReadIntmat(d);
1266             break;
1267    case 19: res->rtyp=BIGINTMAT_CMD;
1268             res->data=ssiReadBigintmat(d);
1269             break;
1270    case 20: ssiReadBlackbox(res,l);
1271             break;
1272    // ------------
1273    case 98: // version
1274             {
1275                int n98_v,n98_m;
1276                BITSET n98_o1,n98_o2;
1277                n98_v=s_readint(d->f_read);
1278                n98_m=s_readint(d->f_read);
1279                n98_o1=s_readint(d->f_read);
1280                n98_o2=s_readint(d->f_read);
1281                if ((n98_v!=SSI_VERSION) ||(n98_m!=MAX_TOK))
1282                {
1283                  Print("incompatible versions of ssi: %d/%d vs %d/%d",
1284                                  SSI_VERSION,MAX_TOK,n98_v,n98_m);
1285                }
1286                #ifndef NDEBUG
1287                if (TEST_OPT_DEBUG)
1288                  Print("// opening ssi-%d, MAX_TOK=%d\n",n98_v,n98_m);
1289                #endif
1290                si_opt_1=n98_o1;
1291                si_opt_2=n98_o2;
1292                return ssiRead1(l);
1293             }
1294    case 99: ssiClose(l); m2_end(0);
1295    case 0: if (s_iseof(d->f_read))
1296            {
1297              ssiClose(l);
1298              res->rtyp=DEF_CMD;
1299              break;
1300            }
1301    default: Werror("not implemented (t:%d)",t);
1302             omFreeSize(res,sizeof(sleftv));
1303             res=NULL;
1304             break;
1305  }
1306  return res;
1307no_ring: WerrorS("no ring");
1308  omFreeSize(res,sizeof(sleftv));
1309  return NULL;
1310}
1311//**************************************************************************/
1312BOOLEAN ssiWrite(si_link l, leftv data)
1313{
1314  if(SI_LINK_W_OPEN_P(l)==0)
1315     if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE;
1316  ssiInfo *d = (ssiInfo *)l->data;
1317  d->level++;
1318  //FILE *fich=d->f;
1319  while (data!=NULL)
1320  {
1321    int tt=data->Typ();
1322    void *dd=data->Data();
1323    if ((dd==NULL) && (data->name!=NULL) && (tt==0)) tt=DEF_CMD;
1324      // return pure undefined names as def
1325
1326    switch(tt /*data->Typ()*/)
1327    {
1328          case NONE/* nothing*/:fputs("16 ",d->f_write);
1329                          break;
1330          case STRING_CMD: fputs("2 ",d->f_write);
1331                           ssiWriteString(d,(char *)dd);
1332                           break;
1333          case INT_CMD: fputs("1 ",d->f_write);
1334                        ssiWriteInt(d,(int)(long)dd);
1335                        break;
1336          case BIGINT_CMD:fputs("4 ",d->f_write);
1337                        ssiWriteBigInt(d,(number)dd);
1338                        break;
1339          case NUMBER_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                          fputs("3 ",d->f_write);
1347                          ssiWriteNumber(d,(number)dd);
1348                        break;
1349          case RING_CMD:fputs("5 ",d->f_write);
1350                        ssiWriteRing(d,(ring)dd);
1351                        break;
1352          case POLY_CMD:
1353          case VECTOR_CMD:
1354                        if (d->r!=currRing)
1355                        {
1356                          fputs("15 ",d->f_write);
1357                          ssiWriteRing(d,currRing);
1358                          if (d->level<=1) fputc('\n',d->f_write);
1359                        }
1360                        if(tt==POLY_CMD) fputs("6 ",d->f_write);
1361                        else             fputs("9 ",d->f_write);
1362                        ssiWritePoly(d,tt,(poly)dd);
1363                        break;
1364          case IDEAL_CMD:
1365          case MODUL_CMD:
1366          case MATRIX_CMD:
1367                        if (d->r!=currRing)
1368                        {
1369                          fputs("15 ",d->f_write);
1370                          ssiWriteRing(d,currRing);
1371                          if (d->level<=1) fputc('\n',d->f_write);
1372                        }
1373                        if(tt==IDEAL_CMD)       fputs("7 ",d->f_write);
1374                        else if(tt==MATRIX_CMD) fputs("8 ",d->f_write);
1375                        else                    fputs("10 ",d->f_write);
1376                        ssiWriteIdeal(d,tt,(ideal)dd);
1377                        break;
1378          case COMMAND:
1379                   fputs("11 ",d->f_write);
1380                   ssiWriteCommand(l,(command)dd);
1381                   break;
1382          case DEF_CMD: /* not evaluated stuff in quotes */
1383                   fputs("12 ",d->f_write);
1384                   ssiWriteString(d,data->Name());
1385                   break;
1386          case PROC_CMD:
1387                   fputs("13 ",d->f_write);
1388                   ssiWriteProc(d,(procinfov)dd);
1389                   break;
1390          case LIST_CMD:
1391                   fputs("14 ",d->f_write);
1392                   ssiWriteList(l,(lists)dd);
1393                   break;
1394          case INTVEC_CMD:
1395                   fputs("17 ",d->f_write);
1396                   ssiWriteIntvec(d,(intvec *)dd);
1397                   break;
1398          case INTMAT_CMD:
1399                   fputs("18 ",d->f_write);
1400                   ssiWriteIntmat(d,(intvec *)dd);
1401                   break;
1402          case BIGINTMAT_CMD:
1403                   fputs("19 ",d->f_write);
1404                   ssiWriteBigintmat(d,(bigintmat *)dd);
1405                   break;
1406          default:
1407            if (tt>MAX_TOK)
1408            {
1409              blackbox *b=getBlackboxStuff(tt);
1410              fputs("20 ",d->f_write);
1411              b->blackbox_serialize(b,dd,l);
1412            }
1413            else
1414            {
1415              Werror("not implemented (t:%d, rtyp:%d)",tt, data->rtyp);
1416              d->level=0;
1417              return TRUE;
1418            }
1419            break;
1420    }
1421    if (d->level<=1) { fputc('\n',d->f_write); fflush(d->f_write); }
1422    data=data->next;
1423  }
1424  d->level--;
1425  return FALSE;
1426}
1427
1428BOOLEAN ssiGetDump(si_link l);
1429BOOLEAN ssiDump(si_link l);
1430
1431si_link_extension slInitSsiExtension(si_link_extension s)
1432{
1433  s->Open=ssiOpen;
1434  s->Close=ssiClose;
1435  s->Kill=ssiClose;
1436  s->Read=ssiRead1;
1437  s->Read2=(slRead2Proc)NULL;
1438  s->Write=ssiWrite;
1439  s->Dump=ssiDump;
1440  s->GetDump=ssiGetDump;
1441
1442  s->Status=slStatusSsi;
1443  s->type="ssi";
1444  return s;
1445}
1446
1447const char* slStatusSsi(si_link l, const char* request)
1448{
1449  ssiInfo *d=(ssiInfo*)l->data;
1450  if (d==NULL) return "not open";
1451  if (((strcmp(l->mode,"fork")==0)
1452  ||(strcmp(l->mode,"tcp")==0)
1453  ||(strcmp(l->mode,"connect")==0))
1454  && (strcmp(request, "read") == 0))
1455  {
1456    fd_set  mask, fdmask;
1457    struct timeval wt;
1458    if (s_isready(d->f_read)) return "ready";
1459    loop
1460    {
1461      /* Don't block. Return socket status immediately. */
1462      wt.tv_sec  = 0;
1463      wt.tv_usec = 0;
1464
1465      FD_ZERO(&mask);
1466      FD_SET(d->fd_read, &mask);
1467      //Print("test fd %d\n",d->fd_read);
1468    /* check with select: chars waiting: no -> not ready */
1469      switch (si_select(d->fd_read+1, &mask, NULL, NULL, &wt))
1470      {
1471        case 0: /* not ready */ return "not ready";
1472        case -1: /*error*/      return "error";
1473        case 1: /*ready ? */    break;
1474      }
1475    /* yes: read 1 char*/
1476    /* if \n, check again with select else ungetc(c), ready*/
1477      int c=s_getc(d->f_read);
1478      //Print("try c=%d\n",c);
1479      if (c== -1) return "eof"; /* eof or error */
1480      else if (isdigit(c))
1481      { s_ungetc(c,d->f_read); return "ready"; }
1482      else if (c>' ')
1483      {
1484        Werror("unknown char in ssiLink(%d)",c);
1485        return "error";
1486      }
1487      /* else: next char */
1488    }
1489  }
1490  else if (strcmp(request, "read") == 0)
1491  {
1492    if (SI_LINK_R_OPEN_P(l) && (!s_iseof(d->f_read)) && (s_isready(d->f_read))) return "ready";
1493    else return "not ready";
1494  }
1495  else if (strcmp(request, "write") == 0)
1496  {
1497    if (SI_LINK_W_OPEN_P(l)) return "ready";
1498    else return "not ready";
1499  }
1500  else return "unknown status request";
1501}
1502
1503int slStatusSsiL(lists L, int timeout)
1504{
1505// input: L: a list with links of type
1506//           ssi-connect, ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch.
1507//           Note: Not every entry in L must be set.
1508//        timeout: timeout for select in micro-seconds
1509//           or -1 for infinity
1510//           or 0 for polling
1511// returns: ERROR (via Werror): L has wrong elements or link not open
1512//           -2: select returns an error
1513//           -1: the read state of all links is eof
1514//           0:  timeout (or polling): none ready,
1515//           i>0: (at least) L[i] is ready
1516  si_link l;
1517  ssiInfo *d;
1518  int d_fd;
1519  fd_set  mask, fdmask;
1520  FD_ZERO(&fdmask);
1521  FD_ZERO(&mask);
1522  int max_fd=0; /* 1 + max fd in fd_set */
1523
1524  /* timeout */
1525  struct timeval wt;
1526  struct timeval *wt_ptr=&wt;
1527  int startingtime = getRTimer()/TIMER_RESOLUTION;  // in seconds
1528  if (timeout== -1)
1529  {
1530    wt_ptr=NULL;
1531  }
1532  else
1533  {
1534    wt.tv_sec  = timeout / 1000000;
1535    wt.tv_usec = timeout % 1000000;
1536  }
1537
1538  /* auxiliary variables */
1539  int i;
1540  int j;
1541  int k;
1542  int s;
1543  char fdmaskempty;
1544
1545  /* check the links and fill in fdmask */
1546  /* check ssi links for ungetc_buf */
1547  for(i=L->nr; i>=0; i--)
1548  {
1549    if (L->m[i].Typ()!=DEF_CMD)
1550    {
1551      if (L->m[i].Typ()!=LINK_CMD)
1552      { WerrorS("all elements must be of type link"); return -2;}
1553      l=(si_link)L->m[i].Data();
1554      if(SI_LINK_OPEN_P(l)==0)
1555      { WerrorS("all links must be open"); return -2;}
1556      if (((strcmp(l->m->type,"ssi")!=0) && (strcmp(l->m->type,"MPtcp")!=0))
1557      || ((strcmp(l->mode,"fork")!=0) && (strcmp(l->mode,"tcp")!=0)
1558        && (strcmp(l->mode,"launch")!=0) && (strcmp(l->mode,"connect")!=0)))
1559      {
1560        WerrorS("all links must be of type ssi:fork, ssi:tcp, ssi:connect");
1561        return -2;
1562      }
1563      if (strcmp(l->m->type,"ssi")==0)
1564      {
1565        d=(ssiInfo*)l->data;
1566        d_fd=d->fd_read;
1567        if (!s_isready(d->f_read))
1568        {
1569          FD_SET(d_fd, &fdmask);
1570          if (d_fd > max_fd) max_fd=d_fd;
1571        }
1572        else
1573          return i+1;
1574      }
1575      else
1576      {
1577        Werror("wrong link type >>%s<<",l->m->type);
1578        return -2;
1579      }
1580    }
1581  }
1582  max_fd++;
1583
1584do_select:
1585  /* copy fdmask to mask */
1586  FD_ZERO(&mask);
1587  for(k = 0; k < max_fd; k++)
1588  {
1589    if(FD_ISSET(k, &fdmask))
1590    {
1591      FD_SET(k, &mask);
1592    }
1593  }
1594
1595  /* check with select: chars waiting: no -> not ready */
1596  #ifdef HAVE_SIMPLEIPC
1597  sipc_semaphore_release(0);
1598  #endif
1599  s = si_select(max_fd, &mask, NULL, NULL, wt_ptr);
1600  #ifdef HAVE_SIMPLEIPC
1601  sipc_semaphore_acquire(0);
1602  #endif
1603
1604  if (s==-1)
1605  {
1606    WerrorS("error in select call");
1607    return -2; /*error*/
1608  }
1609  if (s==0)
1610  {
1611    return 0; /*poll: not ready */
1612  }
1613  else /* s>0, at least one ready  (the number of fd which are ready is s)*/
1614  {
1615    j=0;
1616    while (j<=max_fd) { if (FD_ISSET(j,&mask)) break; j++; }
1617    for(i=L->nr; i>=0; i--)
1618    {
1619      if (L->m[i].rtyp==LINK_CMD)
1620      {
1621        l=(si_link)L->m[i].Data();
1622        if (strcmp(l->m->type,"ssi")==0)
1623        {
1624          d=(ssiInfo*)l->data;
1625          d_fd=d->fd_read;
1626          if(j==d_fd) break;
1627        }
1628        else
1629        {
1630          Werror("wrong link type >>%s<<",l->m->type);
1631          return -2;
1632        }
1633      }
1634    }
1635    // only ssi links:
1636    loop
1637    {
1638      /* yes: read 1 char*/
1639      /* if \n, check again with select else ungetc(c), ready*/
1640      /* setting: d: current ssiInfo, j current fd, i current entry in L*/
1641      int c=s_getc(d->f_read);
1642      //Print("try c=%d\n",c);
1643      if (c== -1) /* eof */
1644      {
1645        FD_CLR(j,&fdmask);
1646        fdmaskempty = 1;
1647        for(k = 0; k < max_fd; k++)
1648        {
1649          if(FD_ISSET(k, &fdmask))
1650          {
1651            fdmaskempty = 0;
1652            break;
1653          }
1654        }
1655        if(fdmaskempty)
1656        {
1657          return -1;
1658        }
1659        if(timeout != -1)
1660        {
1661          timeout = si_max(0,
1662             timeout - 1000000*(getRTimer()/TIMER_RESOLUTION - startingtime));
1663          wt.tv_sec  = timeout / 1000000;
1664          wt.tv_usec = (timeout % 1000000);
1665        }
1666        goto do_select;
1667      }
1668
1669      else if (isdigit(c))
1670      { s_ungetc(c,d->f_read); return i+1; }
1671      else if (c>' ')
1672      {
1673        Werror("unknown char in ssiLink(%d)",c);
1674        return -2;
1675      }
1676      /* else: next char */
1677    }
1678  }
1679}
1680
1681int ssiBatch(const char *host, const char * port)
1682/* return 0 on success, >0 else*/
1683{
1684  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1685  char *buf=(char*)omAlloc(256);
1686  sprintf(buf,"ssi:connect %s:%s",host,port);
1687  slInit(l, buf);
1688  if (slOpen(l,SI_LINK_OPEN,NULL)) return 1;
1689  SI_LINK_SET_RW_OPEN_P(l);
1690
1691  idhdl id = enterid(omStrDup("link_ll"), 0, LINK_CMD, &IDROOT, FALSE);
1692  IDLINK(id) = l;
1693
1694  loop
1695  {
1696    leftv h=ssiRead1(l); /*contains an exit.... */
1697    if (feErrors != NULL && *feErrors != '\0')
1698    {
1699      // handle errors:
1700      PrintS(feErrors); /* currently quite simple */
1701      *feErrors = '\0';
1702    }
1703    ssiWrite(l,h);
1704    h->CleanUp();
1705    omFreeBin(h, sleftv_bin);
1706  }
1707  /* never reached*/
1708  exit(0);
1709}
1710
1711static int ssiReserved_P=0;
1712static int ssiReserved_sockfd;
1713static  struct sockaddr_in ssiResverd_serv_addr;
1714static int  ssiReserved_Clients;
1715int ssiReservePort(int clients)
1716{
1717  if (ssiReserved_P!=0)
1718  {
1719    WerrorS("ERROR already a reverved port requested");
1720    return 0;
1721  }
1722  int portno;
1723  int n;
1724  ssiReserved_sockfd = socket(AF_INET, SOCK_STREAM, 0);
1725  if(ssiReserved_sockfd < 0)
1726  {
1727    WerrorS("ERROR opening socket");
1728    return 0;
1729  }
1730  memset((char *) &ssiResverd_serv_addr,0, sizeof(ssiResverd_serv_addr));
1731  portno = 1025;
1732  ssiResverd_serv_addr.sin_family = AF_INET;
1733  ssiResverd_serv_addr.sin_addr.s_addr = INADDR_ANY;
1734  do
1735  {
1736    portno++;
1737    ssiResverd_serv_addr.sin_port = htons(portno);
1738    if(portno > 50000)
1739    {
1740      WerrorS("ERROR on binding (no free port available?)");
1741      return 0;
1742    }
1743  }
1744  while(bind(ssiReserved_sockfd, (struct sockaddr *) &ssiResverd_serv_addr, sizeof(ssiResverd_serv_addr)) < 0);
1745  ssiReserved_P=portno;
1746  listen(ssiReserved_sockfd,clients);
1747  ssiReserved_Clients=clients;
1748  return portno;
1749}
1750
1751extern si_link_extension si_link_root;
1752si_link ssiCommandLink()
1753{
1754  if (ssiReserved_P==0)
1755  {
1756    WerrorS("ERROR no reverved port requested");
1757    return NULL;
1758  }
1759  struct sockaddr_in cli_addr;
1760  int clilen = sizeof(cli_addr);
1761  int newsockfd = si_accept(ssiReserved_sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
1762  if(newsockfd < 0)
1763  {
1764    Werror("ERROR on accept (errno=%d)",errno);
1765    return NULL;
1766  }
1767  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1768  si_link_extension s = si_link_root;
1769  si_link_extension prev = s;
1770  while (strcmp(s->type, "ssi") != 0)
1771  {
1772    if (s->next == NULL)
1773    {
1774      prev = s;
1775      s = NULL;
1776      break;
1777    }
1778    else
1779    {
1780      s = s->next;
1781    }
1782  }
1783  if (s != NULL)
1784    l->m = s;
1785  else
1786  {
1787    si_link_extension ns = (si_link_extension)omAlloc0Bin(s_si_link_extension_bin);
1788    prev->next=slInitSsiExtension(ns);
1789    l->m = prev->next;
1790  }
1791  l->name=omStrDup("");
1792  l->mode=omStrDup("tcp");
1793  l->ref=1;
1794  ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
1795  l->data=d;
1796  d->fd_read = newsockfd;
1797  d->fd_write = newsockfd;
1798  d->f_read = s_open(newsockfd);
1799  d->f_write = fdopen(newsockfd, "w");
1800  SI_LINK_SET_RW_OPEN_P(l);
1801  ssiReserved_Clients--;
1802  if (ssiReserved_Clients<=0)
1803  {
1804    ssiReserved_P=0;
1805    si_close(ssiReserved_sockfd);
1806  }
1807  return l;
1808}
1809/*---------------------------------------------------------------------*/
1810/**
1811 * @brief additional default signal handler
1812
1813  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
1814  // so use this nice routine here:
1815  //  SuSe 9.x reports -1 always
1816  //  Redhat 9.x/FC x reports sometimes -1
1817  // see also: hpux_system
1818  // also needed by getrusage (timer etc.)
1819
1820 @param[in] sig
1821**/
1822/*---------------------------------------------------------------------*/
1823void sig_chld_hdl(int sig)
1824{
1825  pid_t kidpid;
1826  int status;
1827
1828  loop
1829  {
1830    kidpid = si_waitpid(-1, &status, WNOHANG);
1831    if (kidpid==-1)
1832    {
1833      /* continue on interruption (EINTR): */
1834      if (errno == EINTR) continue;
1835      /* break on anything else (EINVAL or ECHILD according to manpage): */
1836      break;
1837    }
1838    else if (kidpid==0) break; /* no more children to process, so break */
1839
1840    //printf("Child %ld terminated\n", kidpid);
1841    link_list hh=ssiToBeClosed;
1842    while((hh!=NULL)&&(ssiToBeClosed_inactive))
1843    {
1844      if((hh->l!=NULL) && (hh->l->m->Open==ssiOpen))
1845      {
1846        ssiInfo *d = (ssiInfo *)hh->l->data;
1847        if(d->pid==kidpid)
1848        {
1849          if(ssiToBeClosed_inactive)
1850          {
1851            ssiToBeClosed_inactive=FALSE;
1852            slClose(hh->l);
1853            ssiToBeClosed_inactive=TRUE;
1854            break;
1855          }
1856          else break;
1857        }
1858        else hh=(link_list)hh->next;
1859      }
1860      else hh=(link_list)hh->next;
1861    }
1862  }
1863}
1864
1865static BOOLEAN DumpSsiIdhdl(si_link l, idhdl h)
1866{
1867  int type_id = IDTYP(h);
1868
1869  // C-proc not to be dumped, also LIB-proc not
1870  if (type_id == PROC_CMD)
1871  {
1872    if (IDPROC(h)->language == LANG_C) return FALSE;
1873    if (IDPROC(h)->libname != NULL) return FALSE;
1874  }
1875  // do not dump links
1876  if (type_id == LINK_CMD) return FALSE;
1877
1878  // do not dump ssi internal rings: ssiRing*
1879  if ((type_id == RING_CMD) && (strncmp(IDID(h),"ssiRing",7)==0))
1880    return FALSE;
1881
1882  command D=(command)omAlloc0(sizeof(*D));
1883  sleftv tmp;
1884  memset(&tmp,0,sizeof(tmp));
1885  tmp.rtyp=COMMAND;
1886  tmp.data=D;
1887
1888  if (type_id == PACKAGE_CMD)
1889  {
1890    // do not dump Top
1891    if (strcmp(IDID(h), "Top") == 0) return FALSE;
1892    package p=(package)IDDATA(h);
1893    // dump Singular-packages as load("...");
1894    if (p->language==LANG_SINGULAR)
1895    {
1896      D->op=LOAD_CMD;
1897      D->argc=1;
1898      D->arg1.rtyp=STRING_CMD;
1899      D->arg1.data=p->libname;
1900      ssiWrite(l,&tmp);
1901      omFree(D);
1902      return FALSE;
1903    }
1904  }
1905
1906  // handle qrings separately
1907  //if (type_id == QRING_CMD)
1908  //  return DumpSsiQringQring(l, h);
1909
1910  // put type and name
1911  //Print("generic dump:%s,%s\n",IDID(h),Tok2Cmdname(IDTYP(h)));
1912  D->op='=';
1913  D->argc=2;
1914  D->arg1.rtyp=DEF_CMD;
1915  D->arg1.name=IDID(h);
1916  D->arg2.rtyp=IDTYP(h);
1917  D->arg2.data=IDDATA(h);
1918  ssiWrite(l,&tmp);
1919  omFree(D);
1920  return FALSE;
1921}
1922static BOOLEAN ssiDumpIter(si_link l, idhdl h)
1923{
1924  if (h == NULL) return FALSE;
1925
1926  if (ssiDumpIter(l, IDNEXT(h))) return TRUE;
1927
1928  // need to set the ring before writing it, otherwise we get in
1929  // trouble with minpoly
1930  if (IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD)
1931    rSetHdl(h);
1932
1933  if (DumpSsiIdhdl(l, h)) return TRUE;
1934
1935  // do not dump ssi internal rings: ssiRing*
1936  // but dump objects of all other rings
1937  if ((IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD)
1938  && (strncmp(IDID(h),"ssiRing",7)!=0))
1939    return ssiDumpIter(l, IDRING(h)->idroot);
1940  else
1941    return FALSE;
1942}
1943BOOLEAN ssiDump(si_link l)
1944{
1945  idhdl h = IDROOT, rh = currRingHdl;
1946  BOOLEAN status = ssiDumpIter(l, h);
1947
1948  //if (! status ) status = DumpAsciiMaps(fd, h, NULL);
1949
1950  if (currRingHdl != rh) rSetHdl(rh);
1951  //fprintf(fd, "option(set, intvec(%d, %d));\n", si_opt_1, si_opt_2);
1952
1953  return status;
1954}
1955BOOLEAN ssiGetDump(si_link l)
1956{
1957  ssiInfo *d=(ssiInfo*)l->data;
1958  loop
1959  {
1960    if (!SI_LINK_OPEN_P(l)) break;
1961    if (s_iseof(d->f_read)) break;
1962    leftv h=ssiRead1(l); /*contains an exit.... */
1963    if (feErrors != NULL && *feErrors != '\0')
1964    {
1965      // handle errors:
1966      PrintS(feErrors); /* currently quite simple */
1967      return TRUE;
1968      *feErrors = '\0';
1969    }
1970    h->CleanUp();
1971    omFreeBin(h, sleftv_bin);
1972  }
1973  return FALSE;
1974}
1975// ----------------------------------------------------------------
1976// format
1977// 1 int %d
1978// 2 string <len> %s
1979// 3 number
1980// 4 bigint 4 %d or 3 <mpz_t>
1981// 5 ring
1982// 6 poly
1983// 7 ideal
1984// 8 matrix
1985// 9 vector
1986// 10 module
1987// 11 command
1988// 12 def <len> %s
1989// 13 proc <len> %s
1990// 14 list %d <elem1> ....
1991// 15 setring .......
1992// 16 nothing
1993// 17 intvec <len> ...
1994// 18 intmat
1995// 19 bigintmat <r> <c> ...
1996//
1997// 20 blackbox <name> ...
1998//
1999// 98: verify version: <ssi-version> <MAX_TOK> <OPT1> <OPT2>
2000// 99: quit Singular
Note: See TracBrowser for help on using the repository browser.