source: git/Singular/ssiLink.cc @ 3542f7

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