source: git/Singular/ssiLink.cc @ 2404eaa

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