source: git/Singular/ssiLink.cc @ 3f4696

spielwiese
Last change on this file since 3f4696 was 3f4696, checked in by Andreas Steenpaß <steenpas@…>, 14 years ago
ssiLink: bug fixes git-svn-id: file:///usr/local/Singular/svn/trunk@13229 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 28.7 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  SI_LINK_SET_OPEN_P(l, flag);
486  l->data=d;
487  omFree(l->mode);
488  l->mode = omStrDup(mode);
489
490  if (l->name[0] == '\0')
491  {
492    if (strcmp(mode,"fork")==0)
493    {
494      int pc[2];
495      int cp[2];
496      pipe(pc);
497      pipe(cp);
498      pid_t pid=fork();
499      if (pid==0) /*child*/
500      {
501        close(pc[1]); close(cp[0]);
502        d->f_read=fdopen(pc[0],"r");
503        d->fd_read=pc[0];
504        d->f_write=fdopen(cp[1],"w");
505        d->fd_write=cp[1];
506        l->data=d;
507        omFree(l->mode);
508        l->mode = omStrDup(mode);
509        SI_LINK_SET_RW_OPEN_P(l);
510        myynest=0;
511        fe_fgets_stdin=fe_fgets_dummy;
512        if ((u!=NULL)&&(u->rtyp==IDHDL))
513        {
514          idhdl h=(idhdl)u->data;
515          h->lev=0;
516        }
517        loop
518        {
519          leftv h=ssiRead1(l); /*contains an exit.... */
520          if (feErrors != NULL && *feErrors != '\0')
521          {
522            // handle errors:
523            PrintS(feErrors); /* currently quite simple */
524            *feErrors = '\0';
525          }
526          ssiWrite(l,h);
527          h->CleanUp();
528          omFreeBin(h, sleftv_bin);
529        }
530        /* never reached*/
531      }
532      else if (pid>0)
533      {
534        d->pid=pid;
535        close(pc[0]); close(cp[1]);
536        d->f_read=fdopen(cp[0],"r");
537        d->fd_read=cp[0];
538        d->f_write=fdopen(pc[1],"w");
539        d->fd_write=pc[1];
540        SI_LINK_SET_RW_OPEN_P(l);
541      }
542      else
543      {
544        Werror("fork failed (%d)",errno);
545        l->data=NULL;
546        omFree(d);
547        return TRUE;
548      }
549    }
550    else if (strcmp(mode,"tcp")==0)
551    {
552      int sockfd, newsockfd, portno, clilen;
553      struct sockaddr_in serv_addr, cli_addr;
554      int n;
555      sockfd = socket(AF_INET, SOCK_STREAM, 0);
556      if(sockfd < 0)
557      {
558        WerrorS("ERROR opening socket");
559        l->data=NULL;
560        omFree(d);
561        return TRUE;
562      }
563      memset((char *) &serv_addr,0, sizeof(serv_addr));
564      portno = 1024;
565      serv_addr.sin_family = AF_INET;
566      serv_addr.sin_addr.s_addr = INADDR_ANY;
567      do
568      {
569        portno++;
570        serv_addr.sin_port = htons(portno);
571        if(portno > 50000)
572        {
573          WerrorS("ERROR on binding (no free port available?)");
574          l->data=NULL;
575          omFree(d);
576          return TRUE;
577        }
578      }
579      while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
580      Print("waiting on port %d\n", portno);mflush();
581      listen(sockfd,5);
582      newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
583      if(newsockfd < 0)
584      {
585        WerrorS("ERROR on accept");
586        l->data=NULL;
587        omFree(d);
588        return TRUE;
589      }
590      PrintS("client accepted\n");
591      d->fd_read = newsockfd;
592      d->fd_write = newsockfd;
593      d->f_read = fdopen(newsockfd, "r");
594      d->f_write = fdopen(newsockfd, "w");
595      SI_LINK_SET_RW_OPEN_P(l);
596      close(sockfd);
597    }
598    // stdin or stdout
599    else if (flag == SI_LINK_READ)
600    {
601      d->f_read = stdin;
602      mode = "r";
603    }
604    else
605    {
606      d->f_write = stdout;
607      mode = "a";
608    }
609  }
610  else /*l->name=NULL*/
611  {
612    // tcp mode
613    if(strcmp(mode,"tcp")==0)
614    {
615      int sockfd, newsockfd, portno, clilen;
616      struct sockaddr_in serv_addr, cli_addr;
617      int n;
618      sockfd = socket(AF_INET, SOCK_STREAM, 0);
619      if(sockfd < 0)
620      {
621        WerrorS("ERROR opening socket");
622        l->data=NULL;
623        omFree(d);
624        return TRUE;
625      }
626      memset((char *) &serv_addr,0, sizeof(serv_addr));
627      portno = 1024;
628      serv_addr.sin_family = AF_INET;
629      serv_addr.sin_addr.s_addr = INADDR_ANY;
630      do
631      {
632        portno++;
633        serv_addr.sin_port = htons(portno);
634        if(portno > 50000)
635        {
636          WerrorS("ERROR on binding (no free port available?)");
637          l->data=NULL;
638          return TRUE;
639        }
640      }
641      while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
642      //Print("waiting on port %d\n", portno);mflush();
643      listen(sockfd,5);
644      char* cli_host = (char*)omAlloc(256);
645      char* path = (char*)omAlloc(1024);
646      int r = sscanf(l->name,"%255[^:]:%s",cli_host,path);
647      if(r == 0)
648      {
649        WerrorS("ERROR: no host specified");
650        l->data=NULL;
651        omFree(d);
652        return TRUE;
653      }
654      else if(r == 1)
655      {
656        path = "Singular";
657      }
658      char* ssh_command = (char*)omAlloc(256);
659      char* ser_host = (char*)omAlloc(64);
660      gethostname(ser_host,64);
661      sprintf(ssh_command,"ssh %s %s -q --batch --link=ssi --MPhost=%s --MPport=%d &",cli_host,path,ser_host,portno);
662      system(ssh_command);
663      //Print("client on %s started:%s\n",cli_host,path);
664      clilen = sizeof(cli_addr);
665      newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
666      if(newsockfd < 0)
667      {
668        WerrorS("ERROR on accept");
669        l->data=NULL;
670        omFree(d);
671        return TRUE;
672      }
673      //PrintS("client accepted\n");
674      d->fd_read = newsockfd;
675      d->fd_write = newsockfd;
676      d->f_read = fdopen(newsockfd, "r");
677      d->f_write = fdopen(newsockfd, "w");
678      SI_LINK_SET_RW_OPEN_P(l);
679      close(sockfd);
680    }
681    else if(strcmp(mode,"connect")==0)
682    {
683      char* host = (char*)omAlloc(256);
684      int sockfd, portno, n;
685      struct sockaddr_in serv_addr;
686      struct hostent *server;
687 
688      sscanf(l->name,"%255[^:]:%d",host,&portno);
689      //Print("connect to host %s, port %d\n",host,portno);mflush();
690      if (portno!=0)
691      {
692        sockfd = socket(AF_INET, SOCK_STREAM, 0);
693        if (sockfd < 0) { WerrorS("ERROR opening socket"); return TRUE; }
694        server = gethostbyname(host);
695        if (server == NULL) {  WerrorS("ERROR, no such host");  return TRUE; }
696        memset((char *) &serv_addr, 0, sizeof(serv_addr));
697        serv_addr.sin_family = AF_INET;
698        memcpy((char *)&serv_addr.sin_addr.s_addr,
699              (char *)server->h_addr,
700              server->h_length);
701        serv_addr.sin_port = htons(portno);
702        if (connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
703        { WerrorS("ERROR connecting"); return TRUE; }
704        //PrintS("connected\n");mflush();
705        d->f_read=fdopen(sockfd,"r");
706        d->fd_read=sockfd;
707        d->f_write=fdopen(sockfd,"w");
708        d->fd_write=sockfd;
709        SI_LINK_SET_RW_OPEN_P(l);
710        omFree(host);
711      }
712      else
713      {
714        l->data=NULL;
715        omFree(d);
716        return TRUE;
717      }
718    }
719    else
720    {
721      // normal ascii link to a file
722      FILE *outfile;
723      char *filename=l->name;
724
725      if(filename[0]=='>')
726      {
727        if (filename[1]=='>')
728        {
729          filename+=2;
730          mode = "a";
731        }
732        else
733        {
734          filename++;
735          mode="w";
736        }
737      }
738      outfile=myfopen(filename,mode);
739      if (outfile!=NULL)
740      {
741        if (strcmp(l->mode,"r")==0) d->f_read = outfile;
742        else d->f_write = outfile;
743      }
744      else
745      {
746        omFree(d);
747        l->data=NULL;
748        return TRUE;
749      }
750    }
751  }
752
753  return FALSE;
754}
755
756//**************************************************************************/
757LINKAGE BOOLEAN ssiClose(si_link l)
758{
759  ssiInfo *d = (ssiInfo *)l->data;
760  if (d!=NULL)
761  {
762    if ((strcmp(l->mode,"tcp")==0)
763    || (strcmp(l->mode,"fork")==0))
764    {
765      fprintf(d->f_write,"99\n");fflush(d->f_write);
766    }
767    if (d->f_read!=NULL) fclose(d->f_read);
768    if (d->f_write!=NULL) fclose(d->f_write);
769    if (d->r!=NULL) rKill(d->r);
770    if (d->pid!=0) { kill(d->pid,15); kill(d->pid,9); }
771    omFreeSize((ADDRESS)d,(sizeof *d));
772  }
773  l->data=NULL;
774  SI_LINK_SET_CLOSE_P(l);
775  return FALSE;
776}
777
778//**************************************************************************/
779LINKAGE leftv ssiRead1(si_link l)
780{
781  ssiInfo *d = (ssiInfo *)l->data;
782  leftv res=(leftv)omAlloc0(sizeof(sleftv));
783  int t=0;
784  fscanf(d->f_read,"%d",&t);
785  //Print("got type %d\n",t);
786  switch(t)
787  {
788    case 1:res->rtyp=INT_CMD;
789           res->data=(char *)ssiReadInt(d->f_read);
790           break;
791    case 2:res->rtyp=STRING_CMD;
792           res->data=(char *)ssiReadString(d);
793           break;
794    case 3:res->rtyp=NUMBER_CMD;
795           res->data=(char *)ssiReadNumber(d);
796           break;
797    case 4:res->rtyp=BIGINT_CMD;
798           res->data=(char *)ssiReadBigInt(d);
799           break;
800    case 15:
801    case 5:{
802             d->r=ssiReadRing(d);
803             d->r->ref++;
804             res->rtyp=RING_CMD;
805             res->data=(char*)d->r;
806             // we are in the top-level, so set the basering to d->r:
807             ssiSetCurrRing(d->r);
808             if (t==15) return ssiRead1(l);
809           }
810           break;
811    case 6:res->rtyp=POLY_CMD;
812           if (d->r==NULL) goto no_ring;
813           res->data=(char*)ssiReadPoly(d);
814           break;
815    case 7:res->rtyp=IDEAL_CMD;
816           if (d->r==NULL) goto no_ring;
817           res->data=(char*)ssiReadIdeal(d);
818           break;
819    case 8:res->rtyp=MATRIX_CMD;
820           if (d->r==NULL) goto no_ring;
821           res->data=(char*)ssiReadMatrix(d);
822           break;
823    case 9:res->rtyp=VECTOR_CMD;
824           if (d->r==NULL) goto no_ring;
825           res->data=(char*)ssiReadPoly(d);
826           break;
827    case 10:res->rtyp=MODUL_CMD;
828           if (d->r==NULL) goto no_ring;
829           res->data=(char*)ssiReadIdeal(d);
830           break;
831    case 11:
832           {
833             res->rtyp=COMMAND;
834             res->data=ssiReadCommand(l);
835             int nok=res->Eval();
836             if (nok) WerrorS("error in eval");
837             break;
838           }
839    case 12: /*DEF_CMD*/
840           {
841             res->rtyp=0;
842             res->name=(char *)ssiReadString(d);
843             int nok=res->Eval();
844             if (nok) WerrorS("error in name lookup");
845             break;
846           }
847    case 13: res->rtyp=PROC_CMD;
848             res->data=ssiReadProc(d);
849             break;
850    case 14: res->rtyp=LIST_CMD;
851             res->data=ssiReadList(l);
852             break;
853    case 16: res->rtyp=NONE; res->data=NULL;
854             break;
855    case 99: ssiClose(l); exit(0);
856    case 0: if (feof(d->f_read))
857            {
858              ssiClose(l);
859              res->rtyp=DEF_CMD;
860              break;
861            }
862    default: Werror("not implemented (t:%d)",t);
863             omFreeSize(res,sizeof(sleftv));
864             res=NULL;
865             break;
866  }
867  return res;
868no_ring: WerrorS("no ring");
869  return NULL;
870}
871//**************************************************************************/
872LINKAGE BOOLEAN ssiWrite(si_link l, leftv data)
873{
874  if(SI_LINK_W_OPEN_P(l)==0) slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL);
875  ssiInfo *d = (ssiInfo *)l->data;
876  d->level++;
877  //FILE *fich=d->f;
878  while (data!=NULL)
879  {
880    int tt=data->Typ();
881    void *dd=data->Data();
882
883    switch(tt /*data->Typ()*/)
884    {
885          case NONE/* nothing*/:fprintf(d->f_write,"16 ");
886                          break;
887          case STRING_CMD: fprintf(d->f_write,"2 ");
888                           ssiWriteString(d,(char *)dd);
889                           break;
890          case INT_CMD: fprintf(d->f_write,"1 ");
891                        ssiWriteInt(d,(int)(long)dd);
892                        break;
893          case BIGINT_CMD:fprintf(d->f_write,"4 ");
894                        ssiWriteBigInt(d,(number)dd);
895                        break;
896          case NUMBER_CMD:
897                          if (d->r!=currRing)
898                          {
899                            fprintf(d->f_write,"15 ");
900                            ssiWriteRing(d,currRing);
901                            if (d->level<=1) fprintf(d->f_write,"\n");
902                          }
903                          fprintf(d->f_write,"3 ");
904                          ssiWriteNumber(d,(number)dd);
905                        break;
906          case RING_CMD:fprintf(d->f_write,"5 ");
907                        ssiWriteRing(d,(ring)dd);
908                        break;
909          case POLY_CMD:
910          case VECTOR_CMD:
911                        if (d->r!=currRing)
912                        {
913                          fprintf(d->f_write,"15 ");
914                          ssiWriteRing(d,currRing);
915                          if (d->level<=1) fprintf(d->f_write,"\n");
916                        }
917                        if(tt==POLY_CMD) fprintf(d->f_write,"6 ");
918                        else             fprintf(d->f_write,"9 ");
919                        ssiWritePoly(d,tt,(poly)dd);
920                        break;
921          case IDEAL_CMD:
922          case MODUL_CMD:
923          case MATRIX_CMD:
924                        if (d->r!=currRing)
925                        {
926                          fprintf(d->f_write,"15 ");
927                          ssiWriteRing(d,currRing);
928                          if (d->level<=1) fprintf(d->f_write,"\n");
929                        }
930                        if(tt==IDEAL_CMD)       fprintf(d->f_write,"7 ");
931                        else if(tt==MATRIX_CMD) fprintf(d->f_write,"8 ");
932                        else                    fprintf(d->f_write,"10 ");
933                        ssiWriteIdeal(d,tt,(ideal)dd);
934                        break;
935          case COMMAND:
936                   fprintf(d->f_write,"11 ");
937                   ssiWriteCommand(l,(command)dd);
938                   break;
939          case DEF_CMD: /* not evaluated stuff in quotes */
940                   fprintf(d->f_write,"12 ");
941                   ssiWriteString(d,data->Name());
942                   break;
943          case PROC_CMD:
944                   fprintf(d->f_write,"13 ");
945                   ssiWriteProc(d,(procinfov)dd);
946                   break;
947          case LIST_CMD:
948                   fprintf(d->f_write,"14 ");
949                   ssiWriteList(l,(lists)dd);
950                   break;
951          default: Werror("not implemented (t:%d, rtyp:%d)",tt, data->rtyp);
952                   d->level=0;
953                   return TRUE;
954    }
955    if (d->level<=1) { fprintf(d->f_write,"\n"); fflush(d->f_write); }
956    data=data->next;
957  }
958  d->level--;
959  return FALSE;
960}
961
962si_link_extension slInitSsiExtension(si_link_extension s)
963{
964  s->Open=ssiOpen;
965  s->Close=ssiClose;
966  s->Kill=ssiClose;
967  s->Read=ssiRead1;
968  s->Read2=(slRead2Proc)NULL;
969  s->Write=ssiWrite;
970
971  s->Status=slStatusSsi;
972  s->type="ssi";
973  return s;
974}
975const char* slStatusSsi(si_link l, const char* request)
976{
977  ssiInfo *d=(ssiInfo*)l->data;
978  if (d==NULL) return "not open";
979  if (((strcmp(l->mode,"fork")==0)||(strcmp(l->mode,"tcp")==0))
980  && (strcmp(request, "read") == 0))
981  {
982    fd_set  mask, fdmask;
983    struct timeval wt;
984    loop
985    {
986      /* Don't block. Return socket status immediately. */
987      wt.tv_sec  = 0;
988      wt.tv_usec = 0;
989
990      FD_ZERO(&mask);
991      FD_SET(d->fd_read, &mask);
992      //Print("test fd %d\n",d->fd_read);
993    /* check with select: chars waiting: no -> not ready */
994      switch (select(d->fd_read+1, &mask, NULL, NULL, &wt))
995      {
996        case 0: /* not ready */ return "not ready";
997        case -1: /*error*/      return "error";
998        case 1: /*ready ? */    break;
999      }
1000    /* yes: read 1 char*/
1001    /* if \n, check again with select else ungetc(c), ready*/
1002      int c=fgetc(d->f_read);
1003      //Print("try c=%d\n",c);
1004      if (c== -1) return "eof";
1005      else if (isdigit(c))
1006      { ungetc(c,d->f_read); return "ready"; }
1007      else if (c>' ')
1008      {
1009        Werror("unknown char in ssiLink(%d)",c);
1010        return "error";
1011      }
1012      /* else: next char */
1013    }
1014  }
1015  else if (strcmp(request, "read") == 0)
1016  {
1017    if (SI_LINK_R_OPEN_P(l) && (!feof(d->f_read))) return "ready";
1018    else return "not ready";
1019  }
1020  else if (strcmp(request, "write") == 0)
1021  {
1022    if (SI_LINK_W_OPEN_P(l)) return "ready";
1023    else return "not ready";
1024  }
1025  else return "unknown status request";
1026}
1027
1028int slStatusSsiL(lists L, int timeout)
1029{
1030  si_link l;
1031  ssiInfo *d;
1032  fd_set  mask, fdmask;
1033  FD_ZERO(&mask);
1034  int max_fd=0; /* max fd in fd_set */
1035  struct timeval wt;
1036  int i;
1037  for(i=L->nr-1; i>=0; i--)
1038  {
1039    if (L->m[i].Typ()!=LINK_CMD)
1040    { WerrorS("all elements must be of type link"); return -2;}
1041    l=(si_link)L->m[i].Data();
1042    if(SI_LINK_OPEN_P(l)==0)
1043    { WerrorS("all links must be open"); return -2;}
1044    if ((strcmp(l->m->type,"ssi")!=0)
1045    && (strcmp(l->mode,"fork")!=0) || (strcmp(l->mode,"tcp")!=NULL))
1046    { WerrorS("all links must be of type ssi:fork or ssi:tcp"); return -2;}
1047    d=(ssiInfo*)l->data;
1048    FD_SET(d->fd_read, &mask);
1049    if (d->fd_read> max_fd) max_fd=d->fd_read;
1050  }
1051  struct timeval *wt_ptr=&wt;
1052  if (timeout== -1)
1053  {
1054    wt_ptr=NULL;
1055  }
1056  else
1057  {
1058    wt.tv_sec  = timeout / 1000000;
1059    wt.tv_usec = timeout % 1000000;
1060  }
1061  /* check with select: chars waiting: no -> not ready */
1062  int s= select(max_fd, &mask, NULL, NULL, wt_ptr);
1063  if (s==-1) return -2; /*error*/
1064  if (s==0) 
1065  {
1066    return -1; /*poll: not ready */
1067  }
1068  else /* s>0, at least one ready */
1069  {
1070    int j=0;
1071    while (j<=max_fd) { if (FD_ISSET(j,&mask)) break; j++; }
1072    for(i=L->nr-1; i>=0; i--)
1073    {
1074      l=(si_link)L->m[i].Data();
1075      d=(ssiInfo*)l->data;
1076      if(j==d->fd_read) break;
1077    }
1078    loop
1079    {
1080      /* yes: read 1 char*/
1081      /* if \n, check again with select else ungetc(c), ready*/
1082      /* setting: d: current ssiInfo, j current fd, i current entry in L*/
1083      int c=fgetc(d->f_read);
1084      //Print("try c=%d\n",c);
1085      if (c== -1) return 0;
1086      else if (isdigit(c))
1087      { ungetc(c,d->f_read); return i+1; }
1088      else if (c>' ')
1089      {
1090        Werror("unknown char in ssiLink(%d)",c);
1091        return -2;
1092      }
1093      /* else: next char */
1094    }
1095  }
1096}
1097
1098int ssiBatch(const char *host, const char * port)
1099/* return 0 on success, >0 else*/
1100{
1101  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1102  char *buf=(char*)omAlloc(256);
1103  sprintf(buf,"ssi:connect %s:%s",host,port);
1104  slInit(l, buf);
1105  slOpen(l,SI_LINK_OPEN,NULL);
1106  SI_LINK_SET_RW_OPEN_P(l);
1107  loop
1108  {
1109    leftv h=ssiRead1(l); /*contains an exit.... */
1110    if (feErrors != NULL && *feErrors != '\0')
1111    {
1112      // handle errors:
1113      PrintS(feErrors); /* currently quite simple */
1114      *feErrors = '\0';
1115    }
1116    ssiWrite(l,h);
1117    h->CleanUp();
1118    omFreeBin(h, sleftv_bin);
1119  }
1120  /* never reached*/
1121  exit(0);
1122}
1123
1124// ----------------------------------------------------------------
1125// format
1126// 1 int %d
1127// 2 string <len> %s
1128// 3 number
1129// 4 bigint 4 %d or 3 <mpz_t>
1130// 5 ring
1131// 6 poly
1132// 7 ideal
1133// 8 matrix
1134// 9 vector
1135// 10 module
1136// 11 command
1137// 12 def <len> %s
1138// 13 proc <len> %s
1139// 14 list %d <elem1> ....
1140// 15 setring .......
1141// 16 nothing
1142//
1143// 99: quit Singular
Note: See TracBrowser for help on using the repository browser.