source: git/Singular/ssiLink.cc @ bc0078

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