source: git/Singular/ssiLink.cc @ b7b65ee

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