source: git/Singular/ssiLink.cc @ 7626c5f

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