source: git/Singular/ssiLink.cc @ 92d684

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