source: git/Singular/ssiLink.cc @ 5c7641

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