source: git/Singular/ssiLink.cc @ b5f276e

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