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

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