source: git/Singular/ssiLink.cc @ f2df0c3

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