source: git/Singular/ssiLink.cc @ c0b2e03

spielwiese
Last change on this file since c0b2e03 was c0b2e03, checked in by Hans Schoenemann <hannes@…>, 13 years ago
no kill -9 git-svn-id: file:///usr/local/Singular/svn/trunk@14115 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 39.2 KB
RevLine 
[8ed989]1/****************************************
2 * Computer Algebra System SINGULAR     *
3 ****************************************/
4/***************************************************************
5 * File:    ssiLink.h
6 *  Purpose: declaration of sl_link routines for ssi
7 *  Version: $Id$
8 ***************************************************************/
[8f650f3]9#include <stdio.h>
10#include <fcntl.h>
11#include <errno.h>
12#include <unistd.h>
[8ed989]13#include <sys/types.h>
14#include <signal.h>
[76912c]15#include <sys/types.h>          /* for portability */
[8ed989]16#include <sys/select.h>
[76912c]17#include <sys/socket.h>
18#include <netinet/in.h>
[6c2364]19#include <ctype.h>   /*for isdigit*/
[0f4cea]20#include <netdb.h>
[a796fb]21#include <sys/wait.h>
22
[8ed989]23
24
[f2df0c3]25#include <kernel/mod2.h>
26// #include "mod2.h"
[8ed989]27
[f2df0c3]28#include <Singular/tok.h>
29#include <Singular/ipid.h>
[b1dfaf]30#include <omalloc/omalloc.h>
[8ed989]31#include <kernel/ring.h>
32#include <kernel/matpol.h>
33#include <kernel/ideals.h>
34#include <kernel/polys.h>
35#include <kernel/longrat.h>
36#include <kernel/ideals.h>
[4d22d3]37#include <kernel/intvec.h>
[74a04c]38#include <kernel/options.h>
[b14855]39#include <kernel/timer.h>
[f2df0c3]40#include <Singular/subexpr.h>
41#include <Singular/silink.h>
[98918e]42#include <Singular/cntrlc.h>
[f2df0c3]43#include <Singular/lists.h>
44#include <Singular/ssiLink.h>
[8ed989]45
[19bece]46#ifdef HAVE_MPSR
47#include <Singular/mpsr.h>
48#endif
49
[1bf1c0]50//#if (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600)
51//#define HAVE_PSELECT
52//#endif
[a88046d]53
54#define SSI_VERSION 1
55
[8ed989]56typedef struct
57{
58  FILE *f_read;
59  FILE *f_write;
60  ring r;
61  pid_t pid; /* only valid for fork/tcp mode*/
62  int fd_read,fd_write; /* only valid for fork/tcp mode*/
63  char level;
[c45b2a5]64  char ungetc_buf; /* status sets to !=0, if ungetc was used, ssiRead* set to 0*/
[05ed3d]65  char send_quit_at_exit;
[c45b2a5]66
[8ed989]67} ssiInfo;
68
[f47847f]69
70typedef struct
71{
72  leftv u;
73  si_link l;
74  void * next;
75} link_struct;
76
77typedef link_struct* link_list;
78
79link_list ssiToBeClosed=NULL;
[a796fb]80sigset_t ssi_sigmask;
81sigset_t ssi_oldmask;
82#define SSI_BLOCK_CHLD sigprocmask(SIG_SETMASK, &ssi_sigmask, &ssi_oldmask)
83#define SSI_UNBLOCK_CHLD sigprocmask(SIG_SETMASK, &ssi_oldmask, NULL)
[f47847f]84
[8ed989]85// the helper functions:
86void ssiSetCurrRing(const ring r)
87{
88  if (!rEqual(r,currRing,1))
89  {
90    char name[20];
91    int nr=0;
92    do
93    { sprintf(name,"ssiRing%d",nr); nr++; }
94    while(IDROOT->get(name, 0)!=NULL);
95    idhdl h=enterid(omStrDup(name),0,RING_CMD,&IDROOT,FALSE);
96    IDRING(h)=r;
97    r->ref++;
98    rSetHdl(h);
99  }
100}
101// the implementation of the functions:
102void ssiWriteInt(ssiInfo *d,const int i)
103{
[a796fb]104  SSI_BLOCK_CHLD;
[8f650f3]105  fprintf(d->f_write,"%d ",i);
[a796fb]106  SSI_UNBLOCK_CHLD;
[8f650f3]107  //if (d->f_debug!=NULL) fprintf(d->f_debug,"int: %d ",i);
[8ed989]108}
109
110void ssiWriteString(ssiInfo *d,const char *s)
111{
[a796fb]112  SSI_BLOCK_CHLD;
[8f650f3]113  fprintf(d->f_write,"%d %s ",strlen(s),s);
[a796fb]114  SSI_UNBLOCK_CHLD;
[8f650f3]115  //if (d->f_debug!=NULL) fprintf(d->f_debug,"stringi: %d \"%s\" ",strlen(s),s);
[8ed989]116}
117
118
119void ssiWriteBigInt(const ssiInfo *d, const number n)
120{
121  // syntax is as follows:
122  // case 2 Q:     3 4 <int>
123  //        or     3 3 <mpz_t nominator>
[a796fb]124  SSI_BLOCK_CHLD;
[8ed989]125  if(SR_HDL(n) & SR_INT)
126  {
127    fprintf(d->f_write,"4 %ld ",SR_TO_INT(n));
[8f650f3]128    //if (d->f_debug!=NULL) fprintf(d->f_debug,"bigint: short \"%ld\" ",SR_TO_INT(n));
[8ed989]129  }
130  else if (n->s==3)
131  {
[9f8f6a]132    fprintf(d->f_write,"3 ");
133    mpz_out_str(d->f_write,10,n->z);
134    fprintf(d->f_write," ");
135    //gmp_fprintf(d->f_write,"3 %Zd ",n->z);
[8f650f3]136    //if (d->f_debug!=NULL) gmp_fprintf(d->f_debug,"bigint: gmp \"%Zd\" ",n->z);
[8ed989]137  }
138  else Werror("illiegal bigint");
[a796fb]139  SSI_UNBLOCK_CHLD;
[8ed989]140}
141
142void ssiWriteNumber(const ssiInfo *d, const number n)
143{
144  // syntax is as follows:
145  // case 1 Z/p:   3 <int>
146  // case 2 Q:     3 4 <int>
147  //        or     3 0 <mpz_t nominator> <mpz_t denominator>
148  //        or     3 1  dto.
149  //        or     3 3 <mpz_t nominator>
[d8bea6a]150  //        or     3 5 <mpz_t raw nom.> <mpz_t raw denom.>
151  //        or     3 6 <mpz_t raw nom.> <mpz_t raw denom.>
152  //        or     3 7 <mpz_t raw nom.>
[a796fb]153  SSI_BLOCK_CHLD;
[8ed989]154  if(rField_is_Zp(d->r))
155  {
156    fprintf(d->f_write,"%d ",(int)(long)n);
[8f650f3]157    //if (d->f_debug!=NULL) fprintf(d->f_debug,"number: \"%ld\" ",(int)(long)n);
[8ed989]158  }
159  else if (rField_is_Q(d->r))
160  {
161    if(SR_HDL(n) & SR_INT)
162    {
163      fprintf(d->f_write,"4 %ld ",SR_TO_INT(n));
[8f650f3]164      //if (d->f_debug!=NULL) fprintf(d->f_debug,"number: short \"%ld\" ",SR_TO_INT(n));
[8ed989]165    }
166    else if (n->s<2)
167    {
[d8bea6a]168      //gmp_fprintf(d->f_write,"%d %Zd %Zd ",n->s,n->z,n->n);
169      fprintf(d->f_write,"%d ",n->s+5);
170      mpz_out_str (d->f_write,32, n->z);
171      fprintf(d->f_write," ");
172      mpz_out_str (d->f_write,32, n->n);
173      fprintf(d->f_write," ");
174
[8f650f3]175      //if (d->f_debug!=NULL) gmp_fprintf(d->f_debug,"number: s=%d gmp/gmp \"%Zd %Zd\" ",n->s,n->z,n->n);
[8ed989]176    }
177    else /*n->s==3*/
178    {
[d8bea6a]179      //gmp_fprintf(d->f_write,"3 %Zd ",n->z);
180      fprintf(d->f_write,"8 ");
181      mpz_out_str (d->f_write,32, n->z);
182      fprintf(d->f_write," ");
[b65d1d]183
[8f650f3]184      //if (d->f_debug!=NULL) gmp_fprintf(d->f_debug,"number: gmp \"%Zd\" ",n->z);
[8ed989]185    }
186  }
187  else WerrorS("coeff field not implemented");
[a796fb]188  SSI_UNBLOCK_CHLD;
[8ed989]189}
190
191void ssiWriteRing(ssiInfo *d,const ring r)
192{
[a796fb]193  /* 5 <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... */
[8ed989]194  if (d->r!=NULL) rKill(d->r);
195  d->r=r;
196  d->r->ref++;
[a796fb]197  SSI_BLOCK_CHLD;
[8ed989]198  fprintf(d->f_write,"%d %d ",r->ch,r->N);
199
200  int i;
201  for(i=0;i<r->N;i++)
202  {
203    fprintf(d->f_write,"%d %s ",strlen(r->names[i]),r->names[i]);
204  }
205  /* number of orderings:*/
206  i=0;
207  while (r->order[i]!=0) i++;
208  fprintf(d->f_write,"%d ",i);
209  /* each ordering block: */
210  i=0;
211  while(r->order[i]!=0)
212  {
213    fprintf(d->f_write,"%d %d %d ",r->order[i],r->block0[i], r->block1[i]);
214    i++;
215  }
[a796fb]216  SSI_UNBLOCK_CHLD;
[8ed989]217}
218
219void ssiWritePoly(ssiInfo *d, int typ, poly p)
220{
[a796fb]221  SSI_BLOCK_CHLD;
[8ed989]222  fprintf(d->f_write,"%d ",pLength(p));//number of terms
[a796fb]223  SSI_UNBLOCK_CHLD;
[8ed989]224  int i;
225
226  while(p!=NULL)
227  {
228    ssiWriteNumber(d,pGetCoeff(p));
229    //nWrite(fich,pGetCoeff(p));
[a796fb]230    SSI_BLOCK_CHLD;
[8ed989]231    fprintf(d->f_write,"%ld ",p_GetComp(p,d->r));//component
232
233    for(int j=1;j<=rVar(d->r);j++)
234    {
235      fprintf(d->f_write,"%ld ",p_GetExp(p,j,d->r ));//x^j
236    }
237    pIter(p);
[a796fb]238    SSI_UNBLOCK_CHLD;
[8ed989]239  }
240}
241
242void ssiWriteIdeal(ssiInfo *d, int typ,ideal I)
243{
244   // syntax: 7 # of elements <poly 1> <poly2>.....
245   // syntax: 8 <rows> <cols> <poly 1> <poly2>.....
246   matrix M=(matrix)I;
[a796fb]247   SSI_BLOCK_CHLD;
[8ed989]248   if (typ==MATRIX_CMD)
249        fprintf(d->f_write,"%d %d ", MATROWS(M),MATCOLS(M));
250   else
251     fprintf(d->f_write,"%d ",IDELEMS(I));
[a796fb]252    SSI_UNBLOCK_CHLD;
[8ed989]253
254   int i;
255   int tt;
256   if (typ==MODUL_CMD) tt=VECTOR_CMD;
257   else                tt=POLY_CMD;
258
259   for(i=0;i<IDELEMS(I);i++)
260   {
261     ssiWritePoly(d,tt,I->m[i]);
262   }
263}
264void ssiWriteCommand(si_link l, command D)
265{
266  ssiInfo *d=(ssiInfo*)l->data;
267  // syntax: <num ops> <operation> <op1> <op2> ....
[a796fb]268  SSI_BLOCK_CHLD;
[8ed989]269  fprintf(d->f_write,"%d %d ",D->argc,D->op);
[a796fb]270  SSI_UNBLOCK_CHLD;
[8ed989]271  if (D->argc >0) ssiWrite(l, &(D->arg1));
[8f650f3]272  if (D->argc < 4)
273  {
274    if (D->argc >1) ssiWrite(l, &(D->arg2));
275    if (D->argc >2) ssiWrite(l, &(D->arg3));
276  }
[8ed989]277}
278
279void ssiWriteProc(ssiInfo *d,procinfov p)
280{
281  ssiWriteString(d,p->data.s.body);
282}
283
284void ssiWriteList(si_link l,lists dd)
285{
286  ssiInfo *d=(ssiInfo*)l->data;
[a796fb]287  SSI_BLOCK_CHLD;
[8ed989]288  fprintf(d->f_write,"%d ",dd->nr+1);
[a796fb]289  SSI_UNBLOCK_CHLD;
[8ed989]290  int i;
291  for(i=0;i<=dd->nr;i++)
292  {
293    ssiWrite(l,&(dd->m[i]));
294  }
295}
[4d22d3]296void ssiWriteIntvec(ssiInfo *d,intvec * v)
297{
[a796fb]298  SSI_BLOCK_CHLD;
[4d22d3]299  fprintf(d->f_write,"%d ",v->length());
300  int i;
301  for(i=0;i<v->length();i++)
302  {
303    fprintf(d->f_write,"%d ",(*v)[i]);
304  }
[a796fb]305  SSI_UNBLOCK_CHLD;
[4d22d3]306}
[8ed989]307
308char *ssiReadString(ssiInfo *d)
309{
310  char *buf;
311  int l;
[a796fb]312  SSI_BLOCK_CHLD;
[8ed989]313  fscanf(d->f_read,"%d ",&l);
[a796fb]314  SSI_UNBLOCK_CHLD;
[8ed989]315  buf=(char*)omAlloc(l+1);
[a796fb]316  SSI_BLOCK_CHLD;
[8ed989]317  fread(buf,1,l,d->f_read);
[a796fb]318  SSI_UNBLOCK_CHLD;
[8ed989]319  buf[l]='\0';
320  return buf;
321}
322
323int ssiReadInt(FILE *fich)
324{
325  int d;
[a796fb]326  SSI_BLOCK_CHLD;
[8ed989]327  fscanf(fich,"%d",&d);
[a796fb]328  SSI_UNBLOCK_CHLD;
[8ed989]329  return d;
330}
331
332number ssiReadBigInt(ssiInfo *d)
333{
[a796fb]334  int sub_type=-1;
335  SSI_BLOCK_CHLD;
336  fscanf(d->f_read,"%d",&sub_type);
337  SSI_UNBLOCK_CHLD;
338  switch(sub_type)
339  {
[8ed989]340   case 3:
341     {// read int or mpz_t or mpz_t, mpz_t
342       number n=nlRInit(0);
[a796fb]343       SSI_BLOCK_CHLD;
[9f8f6a]344       mpz_inp_str(n->z,d->f_read,0);
[a796fb]345       SSI_UNBLOCK_CHLD;
[8ed989]346       n->s=sub_type;
347       return n;
348     }
[a796fb]349   case 4:
350     {
351       int dd;
352       SSI_BLOCK_CHLD;
353       fscanf(d->f_read,"%d",&dd);
354       SSI_UNBLOCK_CHLD;
355       return INT_TO_SR(dd);
356     }
357   default:
358       Werror("error in reading bigint: invalid subtype %d",sub_type);
359       return NULL;
[8ed989]360   }
361}
362
363number ssiReadNumber(ssiInfo *d)
364{
365  if (rField_is_Q(d->r))
366  {
367     int sub_type=-1;
[a796fb]368     SSI_BLOCK_CHLD;
[8ed989]369     fscanf(d->f_read,"%d",&sub_type);
[a796fb]370     SSI_UNBLOCK_CHLD;
[8ed989]371     switch(sub_type)
372     {
373     case 0:
374     case 1:
[d8bea6a]375       {// read mpz_t, mpz_t
[a796fb]376         number n=nlRInit(0);
377         mpz_init(n->n);
378         SSI_BLOCK_CHLD;
379         gmp_fscanf(d->f_read,"%Zd %Zd",n->z,n->n);
380         SSI_UNBLOCK_CHLD;
381         n->s=sub_type;
382         return n;
[8ed989]383       }
384
385     case 3:
[d8bea6a]386       {// read mpz_t
[8ed989]387         number n=nlRInit(0);
[a796fb]388         SSI_BLOCK_CHLD;
[8ed989]389         gmp_fscanf(d->f_read,"%Zd",n->z);
[a796fb]390         SSI_UNBLOCK_CHLD;
[d8bea6a]391         n->s=3; /*sub_type*/
[8ed989]392         return n;
393       }
[a796fb]394     case 4:
395       {
396         int dd;
397         SSI_BLOCK_CHLD;
398         fscanf(d->f_read,"%d",&dd);
399         SSI_UNBLOCK_CHLD;
400         return INT_TO_SR(dd);
401       }
[d8bea6a]402     case 5:
403     case 6:
404       {// read raw mpz_t, mpz_t
[a796fb]405         number n=nlRInit(0);
406         mpz_init(n->n);
407         SSI_BLOCK_CHLD;
408         mpz_inp_str (n->z, d->f_read, 32);
409         mpz_inp_str (n->n, d->f_read, 32);
410         SSI_UNBLOCK_CHLD;
411         n->s=sub_type-5;
412         return n;
[d8bea6a]413       }
414     case 8:
415       {// read raw mpz_t
[a796fb]416         number n=nlRInit(0);
417         SSI_BLOCK_CHLD;
418         mpz_inp_str (n->z, d->f_read, 32);
419         SSI_UNBLOCK_CHLD;
420         n->s=sub_type=3; /*subtype-5*/
421         return n;
[d8bea6a]422       }
423
[8ed989]424     default: Werror("error in reading number: invalid subtype %d",sub_type);
425              return NULL;
426     }
427  }
428  else if (rField_is_Zp(d->r))
429  {
430    // read int
431    int dd;
[a796fb]432    SSI_BLOCK_CHLD;
[8ed989]433    fscanf(d->f_read,"%d",&dd);
[a796fb]434    SSI_UNBLOCK_CHLD;
[8ed989]435    return (number)dd;
436  }
437  else Werror("coeffs not implemented");
[57dfde6]438  return NULL;
[8ed989]439}
440
441ring ssiReadRing(ssiInfo *d)
442{
[a796fb]443/* syntax is <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... */
[8ed989]444  int ch, N,i,l;
445  char **names;
[a796fb]446  SSI_BLOCK_CHLD;
[8ed989]447  fscanf(d->f_read,"%d %d ",&ch,&N);
[a796fb]448  SSI_UNBLOCK_CHLD;
[8ed989]449  names=(char**)omAlloc(N*sizeof(char*));
450  for(i=0;i<N;i++)
451  {
452    names[i]=ssiReadString(d);
453  }
454  // read the orderings:
455  int num_ord; // number of orderings
[a796fb]456  SSI_BLOCK_CHLD;
[8ed989]457  fscanf(d->f_read,"%d",&num_ord);
[a796fb]458  SSI_UNBLOCK_CHLD;
[8ed989]459  int *ord=(int *)omAlloc0((num_ord+1)*sizeof(int));
460  int *block0=(int *)omAlloc0((num_ord+1)*sizeof(int));
461  int *block1=(int *)omAlloc0((num_ord+1)*sizeof(int));
[a796fb]462  SSI_BLOCK_CHLD;
[8ed989]463  for(i=0;i<num_ord;i++)
464  {
465     fscanf(d->f_read,"%d %d %d",&ord[i],&block0[i],&block1[i]);
466  }
[a796fb]467  SSI_UNBLOCK_CHLD;
[8ed989]468  return rDefault(ch,N,names,num_ord,ord,block0,block1);
469}
470
471poly ssiReadPoly(ssiInfo *D)
472{
473// < # of terms> < term1> < .....
474  int n,i,l;
475  n=ssiReadInt(D->f_read);
476  //Print("poly: terms:%d\n",n);
477  poly p;
478  int j;
479  j=0;
480  poly ret=NULL;
[23206f4]481  poly prev=NULL;
[8ed989]482  for(l=0;l<n;l++) // read n terms
483  {
484// coef,comp.exp1,..exp N
485    p=p_Init(D->r);
486    pGetCoeff(p)=ssiReadNumber(D);
487    int d;
[a796fb]488    SSI_BLOCK_CHLD;
[8ed989]489    fscanf(D->f_read,"%d",&d);
[a796fb]490    SSI_UNBLOCK_CHLD;
[8ed989]491    p_SetComp(p,d,D->r);
492    for(i=1;i<=rVar(D->r);i++)
493    {
[a796fb]494      SSI_BLOCK_CHLD;
[8ed989]495      fscanf(D->f_read,"%d",&d);
[a796fb]496      SSI_UNBLOCK_CHLD;
[8ed989]497      p_SetExp(p,i,d,D->r);
498    }
499    p_Setm(p,D->r);
500    p_Test(p,D->r);
[23206f4]501    if (ret==NULL) ret=p;
502    else           pNext(prev)=p;
503    prev=p;
[8ed989]504 }
505 return ret;
506}
507
508ideal ssiReadIdeal(ssiInfo *d)
509{
510  int n,i;
511  ideal I;
[a796fb]512  SSI_BLOCK_CHLD;
[8ed989]513  fscanf(d->f_read,"%d",&n);
[a796fb]514  SSI_UNBLOCK_CHLD;
[8ed989]515  I=idInit(n,1);
516  for(i=0;i<IDELEMS(I);i++) // read n terms
517  {
518    I->m [i]=ssiReadPoly(d);
519  }
520  return I;
521}
522
523matrix ssiReadMatrix(ssiInfo *d)
524{
525  int n,m,i,j;
[a796fb]526  SSI_BLOCK_CHLD;
[8ed989]527  fscanf(d->f_read,"%d %d",&m,&n);
[a796fb]528  SSI_UNBLOCK_CHLD;
[8ed989]529  matrix M=mpNew(m,n);
530  poly p;
531  for(int i=1;i<=MATROWS(M);i++)
532    for(int j=1;j<=MATCOLS(M);j++)
533    {
534      p=ssiReadPoly(d);
535      MATELEM(M,i,j)=p;
536    }
537  return M;
538}
539
540command ssiReadCommand(si_link l)
541{
542  ssiInfo *d=(ssiInfo*)l->data;
543  // syntax: <num ops> <operation> <op1> <op2> ....
544  command D=(command)omAlloc0(sizeof(*D));
545  int argc,op;
[a796fb]546  SSI_BLOCK_CHLD;
[8ed989]547  fscanf(d->f_read,"%d %d",&argc,&op);
[a796fb]548  SSI_UNBLOCK_CHLD;
[8ed989]549  D->argc=argc; D->op=op;
550  leftv v;
551  if (argc >0)
552  {
553    v=ssiRead1(l);
554    memcpy(&(D->arg1),v,sizeof(*v));
555    omFreeBin(v,sleftv_bin);
556  }
[8f650f3]557  if (argc <4)
[8ed989]558  {
[8f650f3]559    if (D->argc >1)
560    {
561      v=ssiRead1(l);
562      memcpy(&(D->arg2),v,sizeof(*v));
563      omFreeBin(v,sleftv_bin);
564    }
565    if (D->argc >2)
566    {
567      v=ssiRead1(l);
568      memcpy(&(D->arg3),v,sizeof(*v));
569      omFreeBin(v,sleftv_bin);
570    }
[8ed989]571  }
[8f650f3]572  else
[8ed989]573  {
[8f650f3]574    leftv prev=&(D->arg1);
575    argc--;
576    while(argc >0)
577    {
578      v=ssiRead1(l);
579      prev->next=v;
580      prev=v;
581      argc--;
582    }
[8ed989]583  }
584  return D;
585}
586
587procinfov ssiReadProc(ssiInfo *d)
588{
589  char *s=ssiReadString(d);
590  procinfov p=(procinfov)omAlloc0Bin(procinfo_bin);
591  p->language=LANG_SINGULAR;
592  p->libname=omStrDup("");
593  p->procname=omStrDup("");
594  p->data.s.body=s;
595  return p;
596}
597lists ssiReadList(si_link l)
598{
599  ssiInfo *d=(ssiInfo*)l->data;
600  int nr;
[a796fb]601  SSI_BLOCK_CHLD;
[8ed989]602  fscanf(d->f_read,"%d",&nr);
[a796fb]603  SSI_UNBLOCK_CHLD;
[8ed989]604  lists L=(lists)omAlloc(sizeof(*L));
605  L->Init(nr);
606
607  int i;
608  leftv v;
609  for(i=0;i<nr;i++)
610  {
611    v=ssiRead1(l);
612    memcpy(&(L->m[i]),v,sizeof(*v));
613    omFreeBin(v,sleftv_bin);
614  }
615  return L;
616}
[4d22d3]617intvec* ssiReadIntvec(ssiInfo *d)
618{
619  int nr;
[a796fb]620  SSI_BLOCK_CHLD;
[4d22d3]621  fscanf(d->f_read,"%d",&nr);
[a796fb]622  SSI_UNBLOCK_CHLD;
[4d22d3]623  intvec *v=new intvec(nr);
[a796fb]624  SSI_BLOCK_CHLD;
[4d22d3]625  for(int i=0;i<nr;i++)
626  {
627    fscanf(d->f_read,"%d",&((*v)[i]));
628  }
[a796fb]629  SSI_UNBLOCK_CHLD;
[4d22d3]630  return v;
631}
[8ed989]632
633//**************************************************************************/
[a796fb]634
[b5f276e]635BOOLEAN ssiOpen(si_link l, short flag, leftv u)
[8ed989]636{
637  const char *mode;
638  ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
[a796fb]639  sigprocmask(SIG_SETMASK, NULL, &ssi_sigmask);
640  sigaddset(&ssi_sigmask, SIGCHLD);
[8ed989]641  if (flag & SI_LINK_OPEN)
642  {
643    if (l->mode[0] != '\0' && (strcmp(l->mode, "r") == 0))
644      flag = SI_LINK_READ;
645    else flag = SI_LINK_WRITE;
646  }
647
648  if (flag == SI_LINK_READ) mode = "r";
649  else if (strcmp(l->mode, "w") == 0) mode = "w";
650  else if (strcmp(l->mode, "fork") == 0) mode = "fork";
[b4a284]651  else if (strcmp(l->mode, "tcp") == 0) mode = "tcp";
[0f4cea]652  else if (strcmp(l->mode, "connect") == 0) mode = "connect";
[8ed989]653  else mode = "a";
654
655
[3f4696]656  SI_LINK_SET_OPEN_P(l, flag);
657  l->data=d;
658  omFree(l->mode);
659  l->mode = omStrDup(mode);
660
[8ed989]661  if (l->name[0] == '\0')
662  {
663    if (strcmp(mode,"fork")==0)
664    {
[f47847f]665      link_list n=(link_list)omAlloc(sizeof(link_struct));
666      n->u=u;
667      n->l=l;
668      n->next=(void *)ssiToBeClosed;
669      ssiToBeClosed=n;
670
[8ed989]671      int pc[2];
672      int cp[2];
673      pipe(pc);
674      pipe(cp);
675      pid_t pid=fork();
[05ed3d]676      if (pid==0) /*fork: child*/
[8ed989]677      {
[5c7641]678        link_list hh=(link_list)ssiToBeClosed->next;
[4d22d3]679        /* we know: l is the first entry in ssiToBeClosed-list */
[f47847f]680        while(hh!=NULL)
681        {
[5c7641]682          ssiInfo *dd=(ssiInfo*)hh->l->data;
683          fclose(dd->f_read);
684          fclose(dd->f_write);
685          if (dd->r!=NULL) rKill(dd->r);
686          omFreeSize((ADDRESS)dd,(sizeof *dd));
687          hh->l->data=NULL;
688          SI_LINK_SET_CLOSE_P(hh->l);
[4d22d3]689          link_list nn=(link_list)hh->next;
690          omFree(hh);
691          hh=nn;
[f47847f]692        }
[4d22d3]693        ssiToBeClosed->next=NULL;
[8ed989]694        close(pc[1]); close(cp[0]);
695        d->f_read=fdopen(pc[0],"r");
696        d->fd_read=pc[0];
697        d->f_write=fdopen(cp[1],"w");
698        d->fd_write=cp[1];
699        l->data=d;
700        omFree(l->mode);
701        l->mode = omStrDup(mode);
[bc0078]702        singular_in_batchmode=TRUE;
[76912c]703        SI_LINK_SET_RW_OPEN_P(l);
[bb19c5]704        //myynest=0;
[8ed989]705        fe_fgets_stdin=fe_fgets_dummy;
[f47847f]706        if ((u!=NULL)&&(u->rtyp==IDHDL))
707        {
708          idhdl h=(idhdl)u->data;
709          h->lev=0;
710        }
[8ed989]711        loop
712        {
713          leftv h=ssiRead1(l); /*contains an exit.... */
[23206f4]714          if (feErrors != NULL && *feErrors != '\0')
715          {
716            // handle errors:
717            PrintS(feErrors); /* currently quite simple */
718            *feErrors = '\0';
719          }
[8ed989]720          ssiWrite(l,h);
721          h->CleanUp();
722          omFreeBin(h, sleftv_bin);
723        }
[23206f4]724        /* never reached*/
[8ed989]725      }
[05ed3d]726      else if (pid>0) /*fork: parent*/
[8ed989]727      {
728        d->pid=pid;
729        close(pc[0]); close(cp[1]);
730        d->f_read=fdopen(cp[0],"r");
[767349]731        d->fd_read=cp[0];
[8ed989]732        d->f_write=fdopen(pc[1],"w");
[767349]733        d->fd_write=pc[1];
[76912c]734        SI_LINK_SET_RW_OPEN_P(l);
[05ed3d]735        d->send_quit_at_exit=1;
[8ed989]736      }
737      else
738      {
739        Werror("fork failed (%d)",errno);
[3f4696]740        l->data=NULL;
741        omFree(d);
742        return TRUE;
[8ed989]743      }
744    }
[a88046d]745    // ---------------------------------------------------------------------
[0f4cea]746    else if (strcmp(mode,"tcp")==0)
747    {
748      int sockfd, newsockfd, portno, clilen;
749      struct sockaddr_in serv_addr, cli_addr;
750      int n;
751      sockfd = socket(AF_INET, SOCK_STREAM, 0);
752      if(sockfd < 0)
753      {
754        WerrorS("ERROR opening socket");
[3f4696]755        l->data=NULL;
756        omFree(d);
[0f4cea]757        return TRUE;
758      }
759      memset((char *) &serv_addr,0, sizeof(serv_addr));
760      portno = 1024;
761      serv_addr.sin_family = AF_INET;
762      serv_addr.sin_addr.s_addr = INADDR_ANY;
763      do
764      {
765        portno++;
766        serv_addr.sin_port = htons(portno);
767        if(portno > 50000)
768        {
769          WerrorS("ERROR on binding (no free port available?)");
[3f4696]770          l->data=NULL;
771          omFree(d);
[0f4cea]772          return TRUE;
773        }
774      }
775      while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
776      Print("waiting on port %d\n", portno);mflush();
777      listen(sockfd,5);
778      newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
779      if(newsockfd < 0)
780      {
781        WerrorS("ERROR on accept");
[3f4696]782        l->data=NULL;
783        omFree(d);
[0f4cea]784        return TRUE;
785      }
786      PrintS("client accepted\n");
787      d->fd_read = newsockfd;
788      d->fd_write = newsockfd;
789      d->f_read = fdopen(newsockfd, "r");
790      d->f_write = fdopen(newsockfd, "w");
791      SI_LINK_SET_RW_OPEN_P(l);
792      close(sockfd);
793    }
[a88046d]794    // no ssi-Link on stdin or stdout
[8ed989]795    else
796    {
[a88046d]797      Werror("invalid mode >>%s<< for ssi",mode);
798      l->data=NULL;
799      omFree(d);
800      return TRUE;
[8ed989]801    }
[44e1b7f]802  }
[a88046d]803  // =========================================================================
[87288e]804  else /*l->name=NULL*/
[8ed989]805  {
[76912c]806    // tcp mode
807    if(strcmp(mode,"tcp")==0)
[8ed989]808    {
[76912c]809      int sockfd, newsockfd, portno, clilen;
810      struct sockaddr_in serv_addr, cli_addr;
811      int n;
812      sockfd = socket(AF_INET, SOCK_STREAM, 0);
813      if(sockfd < 0)
[8ed989]814      {
[76912c]815        WerrorS("ERROR opening socket");
[3f4696]816        l->data=NULL;
817        omFree(d);
[76912c]818        return TRUE;
[8ed989]819      }
[76912c]820      memset((char *) &serv_addr,0, sizeof(serv_addr));
821      portno = 1024;
822      serv_addr.sin_family = AF_INET;
823      serv_addr.sin_addr.s_addr = INADDR_ANY;
824      do
[8ed989]825      {
[76912c]826        portno++;
827        serv_addr.sin_port = htons(portno);
828        if(portno > 50000)
829        {
830          WerrorS("ERROR on binding (no free port available?)");
[3f4696]831          l->data=NULL;
[76912c]832          return TRUE;
833        }
[8ed989]834      }
[76912c]835      while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
[87288e]836      //Print("waiting on port %d\n", portno);mflush();
[76912c]837      listen(sockfd,5);
[841fec]838      char* cli_host = (char*)omAlloc(256);
839      char* path = (char*)omAlloc(1024);
840      int r = sscanf(l->name,"%255[^:]:%s",cli_host,path);
841      if(r == 0)
842      {
843        WerrorS("ERROR: no host specified");
[3f4696]844        l->data=NULL;
845        omFree(d);
[a1c9770]846        omFree(path);
847        omFree(cli_host);
[841fec]848        return TRUE;
849      }
850      else if(r == 1)
851      {
[74a04c]852        WarnS("program not specified, using /usr/local/bin/Singular");
[8a4a44]853        strcpy(path,"/usr/local/bin/Singular");
[841fec]854      }
855      char* ssh_command = (char*)omAlloc(256);
856      char* ser_host = (char*)omAlloc(64);
857      gethostname(ser_host,64);
[0f4cea]858      sprintf(ssh_command,"ssh %s %s -q --batch --link=ssi --MPhost=%s --MPport=%d &",cli_host,path,ser_host,portno);
[87288e]859      //Print("client on %s started:%s\n",cli_host,path);
[a1c9770]860      omFree(path);
861      omFree(cli_host);
[74a04c]862      if (TEST_OPT_PROT) { Print("running >>%s<<\n",ssh_command); }
[a1c9770]863      system(ssh_command);
864      omFree(ssh_command);
865      omFree(ser_host);
[76912c]866      clilen = sizeof(cli_addr);
867      newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
868      if(newsockfd < 0)
869      {
870        WerrorS("ERROR on accept");
[3f4696]871        l->data=NULL;
872        omFree(d);
[76912c]873        return TRUE;
874      }
[87288e]875      //PrintS("client accepted\n");
[76912c]876      d->fd_read = newsockfd;
877      d->fd_write = newsockfd;
878      d->f_read = fdopen(newsockfd, "r");
879      d->f_write = fdopen(newsockfd, "w");
880      SI_LINK_SET_RW_OPEN_P(l);
[05ed3d]881      d->send_quit_at_exit=1;
[76912c]882      close(sockfd);
[a88046d]883      fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,test,verbose);
[0f4cea]884    }
[a88046d]885    // ----------------------------------------------------------------------
[0f4cea]886    else if(strcmp(mode,"connect")==0)
887    {
888      char* host = (char*)omAlloc(256);
889      int sockfd, portno, n;
890      struct sockaddr_in serv_addr;
891      struct hostent *server;
[f47847f]892
[0f4cea]893      sscanf(l->name,"%255[^:]:%d",host,&portno);
[87288e]894      //Print("connect to host %s, port %d\n",host,portno);mflush();
[0f4cea]895      if (portno!=0)
[841fec]896      {
[0f4cea]897        sockfd = socket(AF_INET, SOCK_STREAM, 0);
898        if (sockfd < 0) { WerrorS("ERROR opening socket"); return TRUE; }
899        server = gethostbyname(host);
900        if (server == NULL) {  WerrorS("ERROR, no such host");  return TRUE; }
901        memset((char *) &serv_addr, 0, sizeof(serv_addr));
902        serv_addr.sin_family = AF_INET;
[87288e]903        memcpy((char *)&serv_addr.sin_addr.s_addr,
[f47847f]904              (char *)server->h_addr,
[0f4cea]905              server->h_length);
906        serv_addr.sin_port = htons(portno);
907        if (connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
908        { WerrorS("ERROR connecting"); return TRUE; }
[f47847f]909        //PrintS("connected\n");mflush();
[0f4cea]910        d->f_read=fdopen(sockfd,"r");
911        d->fd_read=sockfd;
912        d->f_write=fdopen(sockfd,"w");
913        d->fd_write=sockfd;
914        SI_LINK_SET_RW_OPEN_P(l);
[f47847f]915        omFree(host);
[841fec]916      }
[3f4696]917      else
918      {
919        l->data=NULL;
920        omFree(d);
921        return TRUE;
922      }
[8f650f3]923    }
[a88046d]924    // ======================================================================
[8ed989]925    else
926    {
[a88046d]927      // normal link to a file
[76912c]928      FILE *outfile;
929      char *filename=l->name;
930
931      if(filename[0]=='>')
932      {
933        if (filename[1]=='>')
934        {
935          filename+=2;
936          mode = "a";
937        }
938        else
939        {
940          filename++;
941          mode="w";
942        }
943      }
944      outfile=myfopen(filename,mode);
945      if (outfile!=NULL)
946      {
947        if (strcmp(l->mode,"r")==0) d->f_read = outfile;
[a88046d]948        else
949        {
950          d->f_write = outfile;
951          fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,test,verbose);
952        }
[76912c]953      }
954      else
955      {
956        omFree(d);
[3f4696]957        l->data=NULL;
[76912c]958        return TRUE;
959      }
[8ed989]960    }
961  }
962
963  return FALSE;
964}
965
966//**************************************************************************/
967LINKAGE BOOLEAN ssiClose(si_link l)
968{
969  ssiInfo *d = (ssiInfo *)l->data;
970  if (d!=NULL)
971  {
[87288e]972    if ((strcmp(l->mode,"tcp")==0)
973    || (strcmp(l->mode,"fork")==0))
974    {
[05ed3d]975      if (d->send_quit_at_exit)
976      {
977        fprintf(d->f_write,"99\n");fflush(d->f_write);
978      }
[f47847f]979      link_list hh=ssiToBeClosed;
[8a4a44]980      if (hh!=NULL)
[f47847f]981      {
[8a4a44]982        if (hh->l==l)
983        {
984           ssiToBeClosed=(link_list)hh->next;
985           omFreeSize(hh,sizeof(link_struct));
986        }
987        else while(hh!=NULL)
[f47847f]988        {
[8a4a44]989          link_list hhh=(link_list)hh->next;
990          if (hhh->l==l)
991          {
992            hh->next=hhh->next;
993            omFreeSize(hhh,sizeof(link_struct));
994            break;
995          }
996          hh=(link_list)hh->next;
[f47847f]997        }
998      }
[87288e]999    }
[8ed989]1000    if (d->f_read!=NULL) fclose(d->f_read);
1001    if (d->f_write!=NULL) fclose(d->f_write);
1002    if (d->r!=NULL) rKill(d->r);
[a796fb]1003    if (d->pid!=0)
1004    {
1005      int status;
1006      kill(d->pid,15);
1007      waitpid(d->pid,&status,0);
1008    }
[8ed989]1009    omFreeSize((ADDRESS)d,(sizeof *d));
1010  }
1011  l->data=NULL;
1012  SI_LINK_SET_CLOSE_P(l);
1013  return FALSE;
1014}
1015
1016//**************************************************************************/
1017LINKAGE leftv ssiRead1(si_link l)
1018{
1019  ssiInfo *d = (ssiInfo *)l->data;
[c45b2a5]1020  d->ungetc_buf='\0';
[8ed989]1021  leftv res=(leftv)omAlloc0(sizeof(sleftv));
1022  int t=0;
[a796fb]1023  SSI_BLOCK_CHLD;
[8ed989]1024  fscanf(d->f_read,"%d",&t);
[a796fb]1025  SSI_UNBLOCK_CHLD;
[8ed989]1026  //Print("got type %d\n",t);
1027  switch(t)
1028  {
1029    case 1:res->rtyp=INT_CMD;
1030           res->data=(char *)ssiReadInt(d->f_read);
1031           break;
1032    case 2:res->rtyp=STRING_CMD;
1033           res->data=(char *)ssiReadString(d);
1034           break;
1035    case 3:res->rtyp=NUMBER_CMD;
1036           res->data=(char *)ssiReadNumber(d);
1037           break;
1038    case 4:res->rtyp=BIGINT_CMD;
1039           res->data=(char *)ssiReadBigInt(d);
1040           break;
[8f650f3]1041    case 15:
[8ed989]1042    case 5:{
1043             d->r=ssiReadRing(d);
1044             d->r->ref++;
1045             res->rtyp=RING_CMD;
1046             res->data=(char*)d->r;
1047             // we are in the top-level, so set the basering to d->r:
1048             ssiSetCurrRing(d->r);
[8f650f3]1049             if (t==15) return ssiRead1(l);
[8ed989]1050           }
1051           break;
1052    case 6:res->rtyp=POLY_CMD;
1053           if (d->r==NULL) goto no_ring;
1054           res->data=(char*)ssiReadPoly(d);
1055           break;
1056    case 7:res->rtyp=IDEAL_CMD;
1057           if (d->r==NULL) goto no_ring;
1058           res->data=(char*)ssiReadIdeal(d);
1059           break;
1060    case 8:res->rtyp=MATRIX_CMD;
1061           if (d->r==NULL) goto no_ring;
1062           res->data=(char*)ssiReadMatrix(d);
1063           break;
1064    case 9:res->rtyp=VECTOR_CMD;
1065           if (d->r==NULL) goto no_ring;
1066           res->data=(char*)ssiReadPoly(d);
1067           break;
1068    case 10:res->rtyp=MODUL_CMD;
1069           if (d->r==NULL) goto no_ring;
1070           res->data=(char*)ssiReadIdeal(d);
1071           break;
1072    case 11:
1073           {
1074             res->rtyp=COMMAND;
1075             res->data=ssiReadCommand(l);
1076             int nok=res->Eval();
1077             if (nok) WerrorS("error in eval");
1078             break;
1079           }
[8f650f3]1080    case 12: /*DEF_CMD*/
[8ed989]1081           {
1082             res->rtyp=0;
1083             res->name=(char *)ssiReadString(d);
1084             int nok=res->Eval();
1085             if (nok) WerrorS("error in name lookup");
1086             break;
1087           }
1088    case 13: res->rtyp=PROC_CMD;
1089             res->data=ssiReadProc(d);
1090             break;
1091    case 14: res->rtyp=LIST_CMD;
1092             res->data=ssiReadList(l);
1093             break;
[e8c21d]1094    case 16: res->rtyp=NONE; res->data=NULL;
[05241a]1095             break;
[4d22d3]1096    case 17: res->rtyp=INTVEC_CMD;
1097             res->data=ssiReadIntvec(d);
1098             break;
[a88046d]1099    // ------------
1100    case 98: // version
1101             {
1102                int n98_v,n98_m;
1103                BITSET n98_o1,n98_o2;
[a796fb]1104                SSI_BLOCK_CHLD;
[a88046d]1105                fscanf(d->f_read,"%d %d %u %u\n",&n98_v,&n98_m,&n98_o1,&n98_o2);
[a796fb]1106                SSI_UNBLOCK_CHLD;
[a88046d]1107                if ((n98_v!=SSI_VERSION) ||(n98_m!=MAX_TOK))
1108                {
1109                  Print("incompatible versions of ssi: %d/%d vs %d/%d",
1110                                  SSI_VERSION,MAX_TOK,n98_v,n98_m);
1111                }
[44e1b7f]1112                #ifndef NDEBUG
1113                if (TEST_OPT_DEBUG)
1114                  Print("// opening ssi-%d, MAX_TOK=%d\n",n98_v,n98_m);
1115                #endif
[a88046d]1116                test=n98_o1;
1117                verbose=n98_o2;
[44e1b7f]1118                return ssiRead1(l);
[a88046d]1119             }
[8ed989]1120    case 99: ssiClose(l); exit(0);
1121    case 0: if (feof(d->f_read))
1122            {
1123              ssiClose(l);
1124              res->rtyp=DEF_CMD;
1125              break;
1126            }
[76912c]1127    default: Werror("not implemented (t:%d)",t);
[8ed989]1128             omFreeSize(res,sizeof(sleftv));
1129             res=NULL;
1130             break;
1131  }
1132  return res;
1133no_ring: WerrorS("no ring");
[a796fb]1134  omFreeSize(res,sizeof(sleftv));
[8ed989]1135  return NULL;
1136}
1137//**************************************************************************/
1138LINKAGE BOOLEAN ssiWrite(si_link l, leftv data)
1139{
[3f4696]1140  if(SI_LINK_W_OPEN_P(l)==0) slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL);
[8ed989]1141  ssiInfo *d = (ssiInfo *)l->data;
1142  d->level++;
1143  //FILE *fich=d->f;
1144  while (data!=NULL)
1145  {
1146    int tt=data->Typ();
1147    void *dd=data->Data();
1148
1149    switch(tt /*data->Typ()*/)
1150    {
[e8c21d]1151          case NONE/* nothing*/:fprintf(d->f_write,"16 ");
[f47847f]1152                          break;
[8ed989]1153          case STRING_CMD: fprintf(d->f_write,"2 ");
1154                           ssiWriteString(d,(char *)dd);
1155                           break;
1156          case INT_CMD: fprintf(d->f_write,"1 ");
1157                        ssiWriteInt(d,(int)(long)dd);
1158                        break;
1159          case BIGINT_CMD:fprintf(d->f_write,"4 ");
1160                        ssiWriteBigInt(d,(number)dd);
1161                        break;
1162          case NUMBER_CMD:
1163                          if (d->r!=currRing)
1164                          {
[8f650f3]1165                            fprintf(d->f_write,"15 ");
[8ed989]1166                            ssiWriteRing(d,currRing);
1167                            if (d->level<=1) fprintf(d->f_write,"\n");
1168                          }
1169                          fprintf(d->f_write,"3 ");
1170                          ssiWriteNumber(d,(number)dd);
1171                        break;
1172          case RING_CMD:fprintf(d->f_write,"5 ");
1173                        ssiWriteRing(d,(ring)dd);
1174                        break;
1175          case POLY_CMD:
1176          case VECTOR_CMD:
1177                        if (d->r!=currRing)
1178                        {
[8f650f3]1179                          fprintf(d->f_write,"15 ");
[8ed989]1180                          ssiWriteRing(d,currRing);
1181                          if (d->level<=1) fprintf(d->f_write,"\n");
1182                        }
1183                        if(tt==POLY_CMD) fprintf(d->f_write,"6 ");
1184                        else             fprintf(d->f_write,"9 ");
1185                        ssiWritePoly(d,tt,(poly)dd);
1186                        break;
1187          case IDEAL_CMD:
1188          case MODUL_CMD:
1189          case MATRIX_CMD:
1190                        if (d->r!=currRing)
1191                        {
[8f650f3]1192                          fprintf(d->f_write,"15 ");
[8ed989]1193                          ssiWriteRing(d,currRing);
1194                          if (d->level<=1) fprintf(d->f_write,"\n");
1195                        }
1196                        if(tt==IDEAL_CMD)       fprintf(d->f_write,"7 ");
1197                        else if(tt==MATRIX_CMD) fprintf(d->f_write,"8 ");
1198                        else                    fprintf(d->f_write,"10 ");
1199                        ssiWriteIdeal(d,tt,(ideal)dd);
1200                        break;
1201          case COMMAND:
1202                   fprintf(d->f_write,"11 ");
1203                   ssiWriteCommand(l,(command)dd);
1204                   break;
1205          case DEF_CMD: /* not evaluated stuff in quotes */
1206                   fprintf(d->f_write,"12 ");
[8f650f3]1207                   ssiWriteString(d,data->Name());
[8ed989]1208                   break;
1209          case PROC_CMD:
1210                   fprintf(d->f_write,"13 ");
[8f650f3]1211                   ssiWriteProc(d,(procinfov)dd);
1212                   break;
[8ed989]1213          case LIST_CMD:
[8f650f3]1214                   fprintf(d->f_write,"14 ");
1215                   ssiWriteList(l,(lists)dd);
1216                   break;
[4d22d3]1217          case INTVEC_CMD:
1218                   fprintf(d->f_write,"17 ");
1219                   ssiWriteIntvec(d,(intvec *)dd);
1220                   break;
[8f650f3]1221          default: Werror("not implemented (t:%d, rtyp:%d)",tt, data->rtyp);
[8ed989]1222                   d->level=0;
1223                   return TRUE;
1224    }
1225    if (d->level<=1) { fprintf(d->f_write,"\n"); fflush(d->f_write); }
1226    data=data->next;
1227  }
1228  d->level--;
1229  return FALSE;
1230}
1231
1232si_link_extension slInitSsiExtension(si_link_extension s)
1233{
[b5f276e]1234  s->Open=ssiOpen;
1235  s->Close=ssiClose;
1236  s->Kill=ssiClose;
1237  s->Read=ssiRead1;
[8ed989]1238  s->Read2=(slRead2Proc)NULL;
[b5f276e]1239  s->Write=ssiWrite;
[8ed989]1240
1241  s->Status=slStatusSsi;
1242  s->type="ssi";
1243  return s;
1244}
[c45b2a5]1245
[8ed989]1246const char* slStatusSsi(si_link l, const char* request)
1247{
1248  ssiInfo *d=(ssiInfo*)l->data;
[767349]1249  if (d==NULL) return "not open";
[76912c]1250  if (((strcmp(l->mode,"fork")==0)||(strcmp(l->mode,"tcp")==0))
1251  && (strcmp(request, "read") == 0))
[8ed989]1252  {
1253    fd_set  mask, fdmask;
1254    struct timeval wt;
[c45b2a5]1255    if (d->ungetc_buf) return "ready";
[8ed989]1256    loop
1257    {
1258      /* Don't block. Return socket status immediately. */
1259      wt.tv_sec  = 0;
1260      wt.tv_usec = 0;
1261
1262      FD_ZERO(&mask);
1263      FD_SET(d->fd_read, &mask);
[767349]1264      //Print("test fd %d\n",d->fd_read);
[8ed989]1265    /* check with select: chars waiting: no -> not ready */
1266      switch (select(d->fd_read+1, &mask, NULL, NULL, &wt))
1267      {
1268        case 0: /* not ready */ return "not ready";
1269        case -1: /*error*/      return "error";
1270        case 1: /*ready ? */    break;
1271      }
1272    /* yes: read 1 char*/
1273    /* if \n, check again with select else ungetc(c), ready*/
1274      int c=fgetc(d->f_read);
[767349]1275      //Print("try c=%d\n",c);
[bc0078]1276      if (c== -1) return "eof"; /* eof or error */
[6c2364]1277      else if (isdigit(c))
[c45b2a5]1278      { ungetc(c,d->f_read); d->ungetc_buf='\1'; return "ready"; }
[76912c]1279      else if (c>' ')
[8ed989]1280      {
[6c2364]1281        Werror("unknown char in ssiLink(%d)",c);
1282        return "error";
[8ed989]1283      }
[6c2364]1284      /* else: next char */
[8ed989]1285    }
1286  }
1287  else if (strcmp(request, "read") == 0)
1288  {
1289    if (SI_LINK_R_OPEN_P(l) && (!feof(d->f_read))) return "ready";
1290    else return "not ready";
1291  }
1292  else if (strcmp(request, "write") == 0)
1293  {
1294    if (SI_LINK_W_OPEN_P(l)) return "ready";
1295    else return "not ready";
1296  }
1297  else return "unknown status request";
1298}
[19bece]1299
[a00221d]1300int slStatusSsiL(lists L, int timeout)
1301{
[bc0078]1302// input: L: a list with links of type
[1edbcdd]1303//           ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch.
1304//           Note: Not every entry in L must be set.
[42e13c]1305//        timeout: timeout for select in micro-seconds
1306//           or -1 for infinity
1307//           or 0 for polling
1308// returns: ERROR (via Werror): L has wrong elements or link not open
1309//           -2: select returns an error
[1edbcdd]1310//           -1: the read state of all links is eof
1311//           0:  timeout (or polling): none ready,
[42e13c]1312//           i>0: (at least) L[i] is ready
[a00221d]1313  si_link l;
1314  ssiInfo *d;
[19bece]1315  #ifdef HAVE_MPSR
1316  MP_Link_pt dd;
1317  #endif
1318  int d_fd;
[a00221d]1319  fd_set  mask, fdmask;
[1edbcdd]1320  FD_ZERO(&fdmask);
[a00221d]1321  FD_ZERO(&mask);
[1edbcdd]1322  int max_fd=0; /* 1 + max fd in fd_set */
1323
1324  /* timeout */
[fec3bde]1325  #ifdef HAVE_PSELECT
[1edbcdd]1326  struct timespec wt;
1327  struct timespec *wt_ptr=&wt;
[fec3bde]1328  #else
1329  struct timeval wt;
1330  struct timeval *wt_ptr=&wt;
1331  #endif
1332  int startingtime = getRTimer()/TIMER_RESOLUTION;  // in seconds
[1edbcdd]1333  if (timeout== -1)
1334  {
1335    wt_ptr=NULL;
1336  }
1337  else
1338  {
1339    wt.tv_sec  = timeout / 1000000;
[fec3bde]1340  #ifdef HAVE_PSELECT
[1edbcdd]1341    wt.tv_nsec = 1000 * (timeout % 1000000);
[fec3bde]1342  #else
1343    wt.tv_usec = timeout % 1000000;
1344  #endif
[1edbcdd]1345  }
1346
1347  /* signal mask for pselect() */
1348  sigset_t sigmask;
1349  if(sigprocmask(SIG_SETMASK, NULL, &sigmask) < 0)
1350  {
1351    WerrorS("error in sigprocmask()");
1352    return -2;
1353  }
1354  if(sigaddset(&sigmask, SIGCHLD) < 0)
1355  {
1356    WerrorS("error in sigaddset()");
1357    return -2;
1358  }
1359
1360  /* auxiliary variables */
[a00221d]1361  int i;
[1edbcdd]1362  int j;
1363  int k;
1364  int s;
1365  char fdmaskempty;
1366
1367  /* check the links and fill in fdmask */
[6c70ef]1368  for(i=L->nr; i>=0; i--)
[a00221d]1369  {
[7a81686]1370    if (L->m[i].Typ()!=DEF_CMD)
[4fe434]1371    {
[7a81686]1372      if (L->m[i].Typ()!=LINK_CMD)
1373      { WerrorS("all elements must be of type link"); return -2;}
1374      l=(si_link)L->m[i].Data();
1375      if(SI_LINK_OPEN_P(l)==0)
1376      { WerrorS("all links must be open"); return -2;}
1377      if (((strcmp(l->m->type,"ssi")!=0) && (strcmp(l->m->type,"MPtcp")!=0))
1378      || ((strcmp(l->mode,"fork")!=0) && (strcmp(l->mode,"tcp")!=0)
1379        && (strcmp(l->mode,"launch")!=0)))
1380      {
[1edbcdd]1381        WerrorS("all links must be of type ssi:fork, ssi:tcp, MPtcp:fork\n");
1382        WerrorS("or MPtcp:launch");
[7a81686]1383        return -2;
1384      }
[19bece]1385    #ifdef HAVE_MPSR
[7a81686]1386      if (strcmp(l->m->type,"ssi")==0)
1387      {
1388        d=(ssiInfo*)l->data;
1389        d_fd=d->fd_read;
1390      }
1391      else
1392      {
1393        dd=(MP_Link_pt)l->data;
1394        d_fd=((MP_TCP_t *)dd->transp.private1)->sock;
1395      }
1396    #else
[19bece]1397      d=(ssiInfo*)l->data;
1398      d_fd=d->fd_read;
1399    #endif
[1edbcdd]1400      FD_SET(d_fd, &fdmask);
[7a81686]1401      if (d_fd > max_fd) max_fd=d_fd;
1402    }
[a00221d]1403  }
[6c70ef]1404  max_fd++;
[1edbcdd]1405
1406do_select:
1407  /* copy fdmask to mask */
1408  FD_ZERO(&mask);
1409  for(k = 0; k < max_fd; k++)
[a00221d]1410  {
[1edbcdd]1411    if(FD_ISSET(k, &fdmask))
1412    {
1413      FD_SET(k, &mask);
1414    }
[a00221d]1415  }
[1edbcdd]1416
[a00221d]1417  /* check with select: chars waiting: no -> not ready */
[fec3bde]1418  #ifdef HAVE_PSELECT
[1edbcdd]1419  s = pselect(max_fd, &mask, NULL, NULL, wt_ptr, &sigmask);
[fec3bde]1420  #else
[a796fb]1421  SSI_BLOCK_CHLD;
1422  s = select(max_fd, &mask, NULL, NULL, wt_ptr);
1423  SSI_UNBLOCK_CHLD;
1424  #endif
[fec3bde]1425
[8a9bcca]1426  if (s==-1)
[a796fb]1427  {
[8a9bcca]1428    WerrorS("error in select call");
1429    return -2; /*error*/
1430  }
[f47847f]1431  if (s==0)
[a00221d]1432  {
[1edbcdd]1433    return 0; /*poll: not ready */
[a00221d]1434  }
[bc0078]1435  else /* s>0, at least one ready  (the number of fd which are ready is s)*/
[a00221d]1436  {
[bc0078]1437    j=0;
[a00221d]1438    while (j<=max_fd) { if (FD_ISSET(j,&mask)) break; j++; }
[6c70ef]1439    for(i=L->nr; i>=0; i--)
[a00221d]1440    {
[7a81686]1441      if (L->m[i].rtyp==LINK_CMD)
[19bece]1442      {
[7a81686]1443        l=(si_link)L->m[i].Data();
1444        #ifdef HAVE_MPSR
1445        if (strcmp(l->m->type,"ssi")!=0)
1446        {
1447          // for MP links, return here:
1448          dd=(MP_Link_pt)l->data;
1449          d_fd=((MP_TCP_t *)dd->transp.private1)->sock;
1450          if(j==d_fd) return i+1;
1451        }
1452        else
1453        {
1454          d=(ssiInfo*)l->data;
1455          d_fd=d->fd_read;
1456          if(j==d_fd) break;
1457        }
1458        #else
[19bece]1459        d=(ssiInfo*)l->data;
1460        d_fd=d->fd_read;
1461        if(j==d_fd) break;
[7a81686]1462        #endif
[19bece]1463      }
[a00221d]1464    }
[19bece]1465    // only ssi links:
[c45b2a5]1466    if (d->ungetc_buf) return i+1;
[a00221d]1467    loop
1468    {
1469      /* yes: read 1 char*/
1470      /* if \n, check again with select else ungetc(c), ready*/
1471      /* setting: d: current ssiInfo, j current fd, i current entry in L*/
1472      int c=fgetc(d->f_read);
1473      //Print("try c=%d\n",c);
[1edbcdd]1474      if (c== -1) /* eof */
[bc0078]1475      {
[1edbcdd]1476        FD_CLR(j,&fdmask);
1477        fdmaskempty = 1;
1478        for(k = 0; k < max_fd; k++)
1479        {
1480          if(FD_ISSET(k, &fdmask))
1481          {
1482            fdmaskempty = 0;
1483            break;
1484          }
1485        }
1486        if(fdmaskempty)
1487        {
1488          return -1;
1489        }
1490        if(timeout != -1)
1491        {
1492          timeout = si_max(0,
1493               timeout - 1000000*(getRTimer()/TIMER_RESOLUTION - startingtime));
1494          wt.tv_sec  = timeout / 1000000;
[fec3bde]1495          #ifdef HAVE_PSELECT
[1edbcdd]1496          wt.tv_nsec = 1000 * (timeout % 1000000);
[fec3bde]1497          #else
1498          wt.tv_usec = (timeout % 1000000);
1499          #endif
[1edbcdd]1500        }
1501        goto do_select;
[bc0078]1502      }
[1edbcdd]1503
[a00221d]1504      else if (isdigit(c))
[c45b2a5]1505      { ungetc(c,d->f_read); d->ungetc_buf='\1'; return i+1; }
[a00221d]1506      else if (c>' ')
1507      {
1508        Werror("unknown char in ssiLink(%d)",c);
1509        return -2;
1510      }
1511      /* else: next char */
1512    }
1513  }
1514}
1515
[841fec]1516int ssiBatch(const char *host, const char * port)
1517/* return 0 on success, >0 else*/
1518{
[87288e]1519  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1520  char *buf=(char*)omAlloc(256);
1521  sprintf(buf,"ssi:connect %s:%s",host,port);
1522  slInit(l, buf);
[b5f276e]1523  slOpen(l,SI_LINK_OPEN,NULL);
[87288e]1524  SI_LINK_SET_RW_OPEN_P(l);
[b65d1d]1525
1526  idhdl id = enterid(omStrDup("link_ll"), 0, LINK_CMD, &IDROOT, FALSE);
1527  IDLINK(id) = l;
1528
[87288e]1529  loop
[0f4cea]1530  {
[87288e]1531    leftv h=ssiRead1(l); /*contains an exit.... */
1532    if (feErrors != NULL && *feErrors != '\0')
[0f4cea]1533    {
[87288e]1534      // handle errors:
1535      PrintS(feErrors); /* currently quite simple */
1536      *feErrors = '\0';
[0f4cea]1537    }
[87288e]1538    ssiWrite(l,h);
1539    h->CleanUp();
1540    omFreeBin(h, sleftv_bin);
[0f4cea]1541  }
[87288e]1542  /* never reached*/
[0f4cea]1543  exit(0);
[841fec]1544}
1545
[8ed989]1546// ----------------------------------------------------------------
1547// format
1548// 1 int %d
1549// 2 string <len> %s
1550// 3 number
1551// 4 bigint 4 %d or 3 <mpz_t>
1552// 5 ring
1553// 6 poly
1554// 7 ideal
1555// 8 matrix
1556// 9 vector
1557// 10 module
1558// 11 command
1559// 12 def <len> %s
1560// 13 proc <len> %s
1561// 14 list %d <elem1> ....
[8f650f3]1562// 15 setring .......
[05241a]1563// 16 nothing
[4d22d3]1564// 17 intvec <len> ...
[8ed989]1565//
[a88046d]1566// 98: verify version: <ssi-version> <MAX_TOK> <OPT1> <OPT2>
[05241a]1567// 99: quit Singular
Note: See TracBrowser for help on using the repository browser.