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

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