source: git/Singular/links/ssiLink.cc @ 00e336

spielwiese
Last change on this file since 00e336 was 00e336, checked in by Hans Schoenemann <hannes@…>, 11 years ago
fix: include path for tests add: s_buff.*
  • Property mode set to 100644
File size: 50.2 KB
Line 
1/****************************************
2 * Computer Algebra System SINGULAR     *
3 ****************************************/
4/***************************************************************
5 * File:    ssiLink.h
6 *  Purpose: declaration of sl_link routines for ssi
7 ***************************************************************/
8#include <stdio.h>
9#include <fcntl.h>
10#include <errno.h>
11#include <unistd.h>
12#include <sys/types.h>
13#include <signal.h>
14#include <sys/types.h>          /* for portability */
15#include <sys/select.h>
16#include <sys/socket.h>
17#include <netinet/in.h>
18#include <ctype.h>   /*for isdigit*/
19#include <netdb.h>
20#include <sys/wait.h>
21#include <time.h>
22
23
24
25#include "config.h"
26#include <kernel/mod2.h>
27
28#include <Singular/tok.h>
29#include <Singular/ipshell.h>
30#include <Singular/ipid.h>
31#include <omalloc/omalloc.h>
32#include <polys/monomials/ring.h>
33#include <polys/matpol.h>
34#include <kernel/ideals.h>
35#include <kernel/polys.h>
36#include <kernel/longrat.h>
37#include <kernel/ideals.h>
38#include <misc/intvec.h>
39#include <misc/options.h>
40#include <kernel/timer.h>
41#include <Singular/subexpr.h>
42#include <Singular/silink.h>
43#include <Singular/cntrlc.h>
44#include <Singular/lists.h>
45#include <Singular/blackbox.h>
46#include <Singular/links/s_buff.h>
47#include <Singular/links/ssiLink.h>
48
49struct snumber_dummy
50{
51  mpz_t z;
52  mpz_t n;
53  #if defined(LDEBUG)
54  int debug;
55  #endif
56  BOOLEAN s;
57};
58typedef struct snumber_dummy  *number_dummy;
59
60//#if (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600)
61//#define HAVE_PSELECT
62//#endif
63
64#define SSI_VERSION 4
65
66typedef struct
67{
68  s_buff f_read;
69  FILE *f_write;
70  ring r;
71  pid_t pid; /* only valid for fork/tcp mode*/
72  int fd_read,fd_write; /* only valid for fork/tcp mode*/
73  char level;
74  char send_quit_at_exit;
75
76} ssiInfo;
77
78
79link_list ssiToBeClosed=NULL;
80BOOLEAN ssiToBeClosed_inactive=TRUE;
81#define SSI_BLOCK_CHLD sigprocmask(SIG_SETMASK, &ssi_sigmask, &ssi_oldmask)
82#define SSI_UNBLOCK_CHLD sigprocmask(SIG_SETMASK, &ssi_oldmask, NULL)
83
84#define SR_INT 1L
85#define SR_HDL(A) ((long)(A))
86#define SR_TO_INT(SR)   (((long)SR) >> 2)
87
88// the helper functions:
89void ssiSetCurrRing(const ring r)
90{
91  if (!rEqual(r,currRing,1))
92  {
93    char name[20];
94    int nr=0;
95    do
96    { sprintf(name,"ssiRing%d",nr); nr++; }
97    while(IDROOT->get(name, 0)!=NULL);
98    idhdl h=enterid(omStrDup(name),0,RING_CMD,&IDROOT,FALSE);
99    IDRING(h)=r;
100    r->ref++;
101    rSetHdl(h);
102  }
103}
104// the implementation of the functions:
105void ssiWriteInt(ssiInfo *d,const int i)
106{
107  SSI_BLOCK_CHLD;
108  fprintf(d->f_write,"%d ",i);
109  SSI_UNBLOCK_CHLD;
110  //if (d->f_debug!=NULL) fprintf(d->f_debug,"int: %d ",i);
111}
112
113void ssiWriteString(ssiInfo *d,const char *s)
114{
115  SSI_BLOCK_CHLD;
116  fprintf(d->f_write,"%d %s ",(int)strlen(s),s);
117  SSI_UNBLOCK_CHLD;
118  //if (d->f_debug!=NULL) fprintf(d->f_debug,"stringi: %d \"%s\" ",strlen(s),s);
119}
120
121
122void ssiWriteBigInt(const ssiInfo *d, const number n)
123{
124  // syntax is as follows:
125  // case 2 Q:     3 4 <int>
126  //        or     3 3 <mpz_t nominator>
127  SSI_BLOCK_CHLD;
128  if((long)(n) & SR_INT)
129  {
130    fprintf(d->f_write,"4 %ld ",SR_TO_INT(n));
131    //if (d->f_debug!=NULL) fprintf(d->f_debug,"bigint: short \"%ld\" ",SR_TO_INT(n));
132  }
133  else if (((number_dummy)n)->s==3)
134  {
135    fputs("3 ",d->f_write);
136    mpz_out_str(d->f_write,10,((number_dummy)n)->z);
137    fputc(' ',d->f_write);
138    //gmp_fprintf(d->f_write,"3 %Zd ",n->z);
139    //if (d->f_debug!=NULL) gmp_fprintf(d->f_debug,"bigint: gmp \"%Zd\" ",n->z);
140  }
141  else WerrorS("illiegal bigint");
142  SSI_UNBLOCK_CHLD;
143}
144
145void ssiWriteNumber(const ssiInfo *d, const number n)
146{
147  // syntax is as follows:
148  // case 1 Z/p:   3 <int>
149  // case 2 Q:     3 4 <int>
150  //        or     3 0 <mpz_t nominator> <mpz_t denominator>
151  //        or     3 1  dto.
152  //        or     3 3 <mpz_t nominator>
153  //        or     3 5 <mpz_t raw nom.> <mpz_t raw denom.>
154  //        or     3 6 <mpz_t raw nom.> <mpz_t raw denom.>
155  //        or     3 7 <mpz_t raw nom.>
156  SSI_BLOCK_CHLD;
157  if(rField_is_Zp(d->r))
158  {
159    fprintf(d->f_write,"%d ",(int)(long)n);
160    //if (d->f_debug!=NULL) fprintf(d->f_debug,"number: \"%ld\" ",(int)(long)n);
161  }
162  else if (rField_is_Q(d->r))
163  {
164    if(SR_HDL(n) & SR_INT)
165    {
166      fprintf(d->f_write,"4 %ld ",SR_TO_INT(n));
167      //if (d->f_debug!=NULL) fprintf(d->f_debug,"number: short \"%ld\" ",SR_TO_INT(n));
168    }
169    else if (((number_dummy)n)->s<2)
170    {
171      //gmp_fprintf(d->f_write,"%d %Zd %Zd ",n->s,n->z,n->n);
172      fprintf(d->f_write,"%d ",((number_dummy)n)->s+5);
173      mpz_out_str (d->f_write,32, ((number_dummy)n)->z);
174      fputc(' ',d->f_write);
175      mpz_out_str (d->f_write,32, ((number_dummy)n)->n);
176      fputc(' ',d->f_write);
177
178      //if (d->f_debug!=NULL) gmp_fprintf(d->f_debug,"number: s=%d gmp/gmp \"%Zd %Zd\" ",n->s,n->z,n->n);
179    }
180    else /*n->s==3*/
181    {
182      //gmp_fprintf(d->f_write,"3 %Zd ",n->z);
183      fputs("8 ",d->f_write);
184      mpz_out_str (d->f_write,32, ((number_dummy)n)->z);
185      fputc(' ',d->f_write);
186
187      //if (d->f_debug!=NULL) gmp_fprintf(d->f_debug,"number: gmp \"%Zd\" ",n->z);
188    }
189  }
190  else WerrorS("coeff field not implemented");
191  SSI_UNBLOCK_CHLD;
192}
193
194void ssiWriteRing(ssiInfo *d,const ring r)
195{
196  /* 5 <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... */
197  if (d->r!=NULL) rKill(d->r);
198  d->r=r;
199  d->r->ref++;
200  SSI_BLOCK_CHLD;
201  fprintf(d->f_write,"%d %d ",n_GetChar(r->cf),r->N);
202
203  int i;
204  for(i=0;i<r->N;i++)
205  {
206    fprintf(d->f_write,"%d %s ",(int)strlen(r->names[i]),r->names[i]);
207  }
208  /* number of orderings:*/
209  i=0;
210  while (r->order[i]!=0) i++;
211  fprintf(d->f_write,"%d ",i);
212  /* each ordering block: */
213  i=0;
214  while(r->order[i]!=0)
215  {
216    fprintf(d->f_write,"%d %d %d ",r->order[i],r->block0[i], r->block1[i]);
217    switch(r->order[i])
218    {
219      case ringorder_a:
220      case ringorder_wp:
221      case ringorder_Wp:
222      case ringorder_ws:
223      case ringorder_Ws:
224      case ringorder_aa:
225      {
226        int ii;
227        for(ii=r->block0[i];ii<=r->block1[i];ii++)
228          fprintf(d->f_write,"%d ",r->wvhdl[i][ii-r->block0[i]]);
229      }
230      break;
231      case ringorder_a64:
232      case ringorder_M:
233      case ringorder_L:
234      case ringorder_IS:
235        Werror("ring oder not implemented for ssi:%d",r->order[i]);
236        break;
237
238      default: break;
239    }
240    i++;
241  }
242  SSI_UNBLOCK_CHLD;
243}
244
245void ssiWritePoly(ssiInfo *d, int typ, poly p)
246{
247  SSI_BLOCK_CHLD;
248  fprintf(d->f_write,"%d ",pLength(p));//number of terms
249  SSI_UNBLOCK_CHLD;
250
251  while(p!=NULL)
252  {
253    ssiWriteNumber(d,pGetCoeff(p));
254    //nWrite(fich,pGetCoeff(p));
255    SSI_BLOCK_CHLD;
256    fprintf(d->f_write,"%ld ",p_GetComp(p,d->r));//component
257
258    for(int j=1;j<=rVar(d->r);j++)
259    {
260      fprintf(d->f_write,"%ld ",p_GetExp(p,j,d->r ));//x^j
261    }
262    pIter(p);
263    SSI_UNBLOCK_CHLD;
264  }
265}
266
267void ssiWriteIdeal(ssiInfo *d, int typ,ideal I)
268{
269   // syntax: 7 # of elements <poly 1> <poly2>.....
270   // syntax: 8 <rows> <cols> <poly 1> <poly2>.....
271   matrix M=(matrix)I;
272   SSI_BLOCK_CHLD;
273   if (typ==MATRIX_CMD)
274        fprintf(d->f_write,"%d %d ", MATROWS(M),MATCOLS(M));
275   else
276     fprintf(d->f_write,"%d ",IDELEMS(I));
277    SSI_UNBLOCK_CHLD;
278
279   int i;
280   int tt;
281   if (typ==MODUL_CMD) tt=VECTOR_CMD;
282   else                tt=POLY_CMD;
283
284   for(i=0;i<IDELEMS(I);i++)
285   {
286     ssiWritePoly(d,tt,I->m[i]);
287   }
288}
289void ssiWriteCommand(si_link l, command D)
290{
291  ssiInfo *d=(ssiInfo*)l->data;
292  // syntax: <num ops> <operation> <op1> <op2> ....
293  SSI_BLOCK_CHLD;
294  fprintf(d->f_write,"%d %d ",D->argc,D->op);
295  SSI_UNBLOCK_CHLD;
296  if (D->argc >0) ssiWrite(l, &(D->arg1));
297  if (D->argc < 4)
298  {
299    if (D->argc >1) ssiWrite(l, &(D->arg2));
300    if (D->argc >2) ssiWrite(l, &(D->arg3));
301  }
302}
303
304void ssiWriteProc(ssiInfo *d,procinfov p)
305{
306  if (p->data.s.body==NULL)
307    iiGetLibProcBuffer(p);
308  if (p->data.s.body!=NULL)
309    ssiWriteString(d,p->data.s.body);
310  else
311    ssiWriteString(d,"");
312}
313
314void ssiWriteList(si_link l,lists dd)
315{
316  ssiInfo *d=(ssiInfo*)l->data;
317  SSI_BLOCK_CHLD;
318  fprintf(d->f_write,"%d ",dd->nr+1);
319  SSI_UNBLOCK_CHLD;
320  int i;
321  for(i=0;i<=dd->nr;i++)
322  {
323    ssiWrite(l,&(dd->m[i]));
324  }
325}
326void ssiWriteIntvec(ssiInfo *d,intvec * v)
327{
328  SSI_BLOCK_CHLD;
329  fprintf(d->f_write,"%d ",v->length());
330  int i;
331  for(i=0;i<v->length();i++)
332  {
333    fprintf(d->f_write,"%d ",(*v)[i]);
334  }
335  SSI_UNBLOCK_CHLD;
336}
337void ssiWriteIntmat(ssiInfo *d,intvec * v)
338{
339  SSI_BLOCK_CHLD;
340  fprintf(d->f_write,"%d %d ",v->rows(),v->cols());
341  int i;
342  for(i=0;i<v->length();i++)
343  {
344    fprintf(d->f_write,"%d ",(*v)[i]);
345  }
346  SSI_UNBLOCK_CHLD;
347}
348
349char *ssiReadString(ssiInfo *d)
350{
351  char *buf;
352  int l;
353  l=s_readint(d->f_read);
354  buf=(char*)omAlloc0(l+1);
355  int c =s_getc(d->f_read); /* skip ' '*/
356  int ll=s_readbytes(buf,l,d->f_read);
357  //if (ll!=l) printf("want %d, got %d bytes\n",l,ll);
358  buf[l]='\0';
359  return buf;
360}
361
362int ssiReadInt(s_buff fich)
363{
364  return s_readint(fich);
365}
366
367number ssiReadBigInt(ssiInfo *d)
368{
369  int sub_type=-1;
370  sub_type=s_readint(d->f_read);
371  switch(sub_type)
372  {
373   case 3:
374     {// read int or mpz_t or mpz_t, mpz_t
375       number n=(number)omAlloc0(sizeof(snumber_dummy));
376       s_readmpz(d->f_read,((number_dummy)n)->z);
377       ((number_dummy)n)->s=sub_type;
378       return n;
379     }
380   case 4:
381     {
382       int dd;
383       dd=s_readint(d->f_read);
384       return n_Init(dd,d->r->cf);
385     }
386   default:
387       Werror("error in reading bigint: invalid subtype %d",sub_type);
388       return NULL;
389   }
390}
391
392number ssiReadNumber(ssiInfo *d)
393{
394  if (rField_is_Q(d->r))
395  {
396     int sub_type=s_readint(d->f_read);
397     switch(sub_type)
398     {
399     case 0:
400     case 1:
401       {// read mpz_t, mpz_t
402         number n=(number)omAlloc0(sizeof(snumber_dummy));
403         mpz_init(((number_dummy)n)->z);
404         mpz_init(((number_dummy)n)->n);
405         s_readmpz(d->f_read,((number_dummy)n)->z);
406         s_readmpz(d->f_read,((number_dummy)n)->n);
407         ((number_dummy)n)->s=sub_type;
408         return n;
409       }
410
411     case 3:
412       {// read mpz_t
413         number n=(number)omAlloc0(sizeof(snumber_dummy));
414         mpz_init(((number_dummy)n)->z);
415         s_readmpz(d->f_read,((number_dummy)n)->z);
416         ((number_dummy)n)->s=3; /*sub_type*/
417         return n;
418       }
419     case 4:
420       {
421         int dd=s_readint(d->f_read);
422         return n_Init(dd,d->r->cf);
423       }
424     case 5:
425     case 6:
426       {// read raw mpz_t, mpz_t
427         number n=(number)omAlloc0(sizeof(snumber_dummy));
428         mpz_init(((number_dummy)n)->z);
429         mpz_init(((number_dummy)n)->n);
430         s_readmpz_base (d->f_read,((number_dummy)n)->z, 32);
431         s_readmpz_base (d->f_read,((number_dummy)n)->n, 32);
432         ((number_dummy)n)->s=sub_type-5;
433         return n;
434       }
435     case 8:
436       {// read raw mpz_t
437         number n=(number)omAlloc0(sizeof(snumber_dummy));
438         mpz_init(((number_dummy)n)->z);
439         s_readmpz_base (d->f_read,((number_dummy)n)->z, 32);
440         ((number_dummy)n)->s=sub_type=3; /*subtype-5*/
441         return n;
442       }
443
444     default: Werror("error in reading number: invalid subtype %d",sub_type);
445              return NULL;
446     }
447  }
448  else if (rField_is_Zp(d->r))
449  {
450    // read int
451    int dd=s_readint(d->f_read);
452    return (number)dd;
453  }
454  else Werror("coeffs not implemented");
455  return NULL;
456}
457
458ring ssiReadRing(ssiInfo *d)
459{
460/* syntax is <ch> <N> <l1> <v1> ...<lN> <vN> <number of orderings> <ord1> <block0_1> <block1_1> .... */
461  int ch, N,i;
462  char **names;
463  ch=s_readint(d->f_read);
464  N=s_readint(d->f_read);
465  names=(char**)omAlloc(N*sizeof(char*));
466  for(i=0;i<N;i++)
467  {
468    names[i]=ssiReadString(d);
469  }
470  // read the orderings:
471  int num_ord; // number of orderings
472  num_ord=s_readint(d->f_read);
473  int *ord=(int *)omAlloc0((num_ord+1)*sizeof(int));
474  int *block0=(int *)omAlloc0((num_ord+1)*sizeof(int));
475  int *block1=(int *)omAlloc0((num_ord+1)*sizeof(int));
476  int **wvhdl=(int**)omAlloc0((num_ord+1)*sizeof(int*));
477  for(i=0;i<num_ord;i++)
478  {
479    ord[i]=s_readint(d->f_read);
480    block0[i]=s_readint(d->f_read);
481    block1[i]=s_readint(d->f_read);
482    switch(ord[i])
483    {
484      case ringorder_a:
485      case ringorder_wp:
486      case ringorder_Wp:
487      case ringorder_ws:
488      case ringorder_Ws:
489      case ringorder_aa:
490      {
491        wvhdl[i]=(int*)omAlloc((block1[i]-block0[i]+1)*sizeof(int));
492        int ii;
493        for(ii=block0[i];ii<=block1[i];ii++)
494          wvhdl[i][ii-block0[i]]=s_readint(d->f_read);
495      }
496      break;
497
498      case ringorder_a64:
499      case ringorder_M:
500      case ringorder_L:
501      case ringorder_IS:
502        Werror("ring oder not implemented for ssi:%d",ord[i]);
503        break;
504
505      default: break;
506    }
507  }
508  return rDefault(ch,N,names,num_ord,ord,block0,block1,wvhdl);
509}
510
511poly ssiReadPoly(ssiInfo *D)
512{
513// < # of terms> < term1> < .....
514  int n,i,l;
515  n=ssiReadInt(D->f_read);
516  //Print("poly: terms:%d\n",n);
517  poly p;
518  int j;
519  j=0;
520  poly ret=NULL;
521  poly prev=NULL;
522  for(l=0;l<n;l++) // read n terms
523  {
524// coef,comp.exp1,..exp N
525    p=p_Init(D->r);
526    pGetCoeff(p)=ssiReadNumber(D);
527    int d=s_readint(D->f_read);
528    p_SetComp(p,d,D->r);
529    for(i=1;i<=rVar(D->r);i++)
530    {
531      d=s_readint(D->f_read);
532      p_SetExp(p,i,d,D->r);
533    }
534    p_Setm(p,D->r);
535    p_Test(p,D->r);
536    if (ret==NULL) ret=p;
537    else           pNext(prev)=p;
538    prev=p;
539 }
540 return ret;
541}
542
543ideal ssiReadIdeal(ssiInfo *d)
544{
545  int i;
546  int n=s_readint(d->f_read);
547  ideal I=idInit(n,1);
548  for(i=0;i<IDELEMS(I);i++) // read n terms
549  {
550    I->m [i]=ssiReadPoly(d);
551  }
552  return I;
553}
554
555matrix ssiReadMatrix(ssiInfo *d)
556{
557  int m=s_readint(d->f_read);
558  int n=s_readint(d->f_read);
559  matrix M=mpNew(m,n);
560  poly p;
561  for(int i=1;i<=MATROWS(M);i++)
562    for(int j=1;j<=MATCOLS(M);j++)
563    {
564      p=ssiReadPoly(d);
565      MATELEM(M,i,j)=p;
566    }
567  return M;
568}
569
570command ssiReadCommand(si_link l)
571{
572  ssiInfo *d=(ssiInfo*)l->data;
573  // syntax: <num ops> <operation> <op1> <op2> ....
574  command D=(command)omAlloc0(sizeof(*D));
575  int argc,op;
576  argc=s_readint(d->f_read);
577  op=s_readint(d->f_read);
578  D->argc=argc; D->op=op;
579  leftv v;
580  if (argc >0)
581  {
582    v=ssiRead1(l);
583    memcpy(&(D->arg1),v,sizeof(*v));
584    omFreeBin(v,sleftv_bin);
585  }
586  if (argc <4)
587  {
588    if (D->argc >1)
589    {
590      v=ssiRead1(l);
591      memcpy(&(D->arg2),v,sizeof(*v));
592      omFreeBin(v,sleftv_bin);
593    }
594    if (D->argc >2)
595    {
596      v=ssiRead1(l);
597      memcpy(&(D->arg3),v,sizeof(*v));
598      omFreeBin(v,sleftv_bin);
599    }
600  }
601  else
602  {
603    leftv prev=&(D->arg1);
604    argc--;
605    while(argc >0)
606    {
607      v=ssiRead1(l);
608      prev->next=v;
609      prev=v;
610      argc--;
611    }
612  }
613  return D;
614}
615
616procinfov ssiReadProc(ssiInfo *d)
617{
618  char *s=ssiReadString(d);
619  procinfov p=(procinfov)omAlloc0Bin(procinfo_bin);
620  p->language=LANG_SINGULAR;
621  p->libname=omStrDup("");
622  p->procname=omStrDup("");
623  p->data.s.body=s;
624  return p;
625}
626lists ssiReadList(si_link l)
627{
628  ssiInfo *d=(ssiInfo*)l->data;
629  int nr=s_readint(d->f_read);
630  lists L=(lists)omAlloc(sizeof(*L));
631  L->Init(nr);
632
633  int i;
634  leftv v;
635  for(i=0;i<nr;i++)
636  {
637    v=ssiRead1(l);
638    memcpy(&(L->m[i]),v,sizeof(*v));
639    omFreeBin(v,sleftv_bin);
640  }
641  return L;
642}
643intvec* ssiReadIntvec(ssiInfo *d)
644{
645  int nr=s_readint(d->f_read);
646  intvec *v=new intvec(nr);
647  for(int i=0;i<nr;i++)
648  {
649    (*v)[i]=s_readint(d->f_read);
650  }
651  return v;
652}
653intvec* ssiReadIntmat(ssiInfo *d)
654{
655  int r,c;
656  r=s_readint(d->f_read);
657  c=s_readint(d->f_read);
658  intvec *v=new intvec(r,c,0);
659  for(int i=0;i<r*c;i++)
660  {
661    (*v)[i]=s_readint(d->f_read);
662  }
663  return v;
664}
665
666void ssiReadBlackbox(leftv res, si_link l)
667{
668  ssiInfo *d=(ssiInfo*)l->data;
669  int throwaway=s_readint(d->f_read);
670  char *name=ssiReadString(d);
671  int tok;
672  blackboxIsCmd(name,tok);
673  if (tok>MAX_TOK)
674  {
675    blackbox *b=getBlackboxStuff(tok);
676    res->rtyp=tok;
677    b->blackbox_deserialize(&b,&(res->data),l);
678  }
679  else
680  {
681    Werror("blackbox %s not found",name);
682  }
683}
684
685//**************************************************************************/
686
687BOOLEAN ssiOpen(si_link l, short flag, leftv u)
688{
689  if (l!=NULL)
690  {
691    const char *mode;
692    ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
693    sigprocmask(SIG_SETMASK, NULL, &ssi_sigmask);
694    sigaddset(&ssi_sigmask, SIGCHLD);
695    if (flag & SI_LINK_OPEN)
696    {
697      if (l->mode[0] != '\0' && (strcmp(l->mode, "r") == 0))
698        flag = SI_LINK_READ;
699      else flag = SI_LINK_WRITE;
700    }
701
702    if (flag == SI_LINK_READ) mode = "r";
703    else if (strcmp(l->mode, "w") == 0) mode = "w";
704    else if (strcmp(l->mode, "fork") == 0) mode = "fork";
705    else if (strcmp(l->mode, "tcp") == 0) mode = "tcp";
706    else if (strcmp(l->mode, "connect") == 0) mode = "connect";
707    else mode = "a";
708
709
710    SI_LINK_SET_OPEN_P(l, flag);
711    l->data=d;
712    omFree(l->mode);
713    l->mode = omStrDup(mode);
714
715    if (l->name[0] == '\0')
716    {
717      if (strcmp(mode,"fork")==0)
718      {
719        link_list n=(link_list)omAlloc(sizeof(link_struct));
720        n->u=u;
721        n->l=l;
722        n->next=(void *)ssiToBeClosed;
723        ssiToBeClosed=n;
724
725        int pc[2];
726        int cp[2];
727        SSI_BLOCK_CHLD;
728        pipe(pc);
729        pipe(cp);
730        pid_t pid=fork();
731        SSI_UNBLOCK_CHLD;
732        if (pid==0) /*fork: child*/
733        {
734          link_list hh=(link_list)ssiToBeClosed->next;
735          /* we know: l is the first entry in ssiToBeClosed-list */
736          while(hh!=NULL)
737          {
738            SI_LINK_SET_CLOSE_P(hh->l);
739            ssiInfo *dd=(ssiInfo*)hh->l->data;
740            SSI_BLOCK_CHLD;
741            s_close(dd->f_read);
742            fclose(dd->f_write);
743            SSI_UNBLOCK_CHLD;
744            if (dd->r!=NULL) rKill(dd->r);
745            omFreeSize((ADDRESS)dd,(sizeof *dd));
746            hh->l->data=NULL;
747            link_list nn=(link_list)hh->next;
748            omFree(hh);
749            hh=nn;
750          }
751          ssiToBeClosed->next=NULL;
752          SSI_BLOCK_CHLD;
753          close(pc[1]); close(cp[0]);
754          d->f_write=fdopen(cp[1],"w");
755          SSI_UNBLOCK_CHLD;
756          d->f_read=s_open(pc[0]);
757          d->fd_read=pc[0];
758          d->fd_write=cp[1];
759          l->data=d;
760          omFree(l->mode);
761          l->mode = omStrDup(mode);
762          singular_in_batchmode=TRUE;
763          SI_LINK_SET_RW_OPEN_P(l);
764          //myynest=0;
765          fe_fgets_stdin=fe_fgets_dummy;
766          WerrorS_callback=WerrorS_batch;
767          if ((u!=NULL)&&(u->rtyp==IDHDL))
768          {
769            idhdl h=(idhdl)u->data;
770            h->lev=0;
771          }
772          loop
773          {
774            leftv h=ssiRead1(l); /*contains an exit.... */
775            if (feErrors != NULL && *feErrors != '\0')
776            {
777              // handle errors:
778              PrintS(feErrors); /* currently quite simple */
779              *feErrors = '\0';
780            }
781            ssiWrite(l,h);
782            h->CleanUp();
783            omFreeBin(h, sleftv_bin);
784          }
785          /* never reached*/
786        }
787        else if (pid>0) /*fork: parent*/
788        {
789          d->pid=pid;
790          SSI_BLOCK_CHLD;
791          close(pc[0]); close(cp[1]);
792          d->f_write=fdopen(pc[1],"w");
793          SSI_UNBLOCK_CHLD;
794          d->f_read=s_open(cp[0]);
795          d->fd_read=cp[0];
796          d->fd_write=pc[1];
797          SI_LINK_SET_RW_OPEN_P(l);
798          d->send_quit_at_exit=1;
799        }
800        else
801        {
802          Werror("fork failed (%d)",errno);
803          l->data=NULL;
804          omFree(d);
805          return TRUE;
806        }
807      }
808      // ---------------------------------------------------------------------
809      else if (strcmp(mode,"tcp")==0)
810      {
811        int sockfd, newsockfd, portno, clilen;
812        struct sockaddr_in serv_addr, cli_addr;
813        sockfd = socket(AF_INET, SOCK_STREAM, 0);
814        if(sockfd < 0)
815        {
816          WerrorS("ERROR opening socket");
817          l->data=NULL;
818          omFree(d);
819          return TRUE;
820        }
821        memset((char *) &serv_addr,0, sizeof(serv_addr));
822        portno = 1025;
823        serv_addr.sin_family = AF_INET;
824        serv_addr.sin_addr.s_addr = INADDR_ANY;
825        do
826        {
827          portno++;
828          serv_addr.sin_port = htons(portno);
829          if(portno > 50000)
830          {
831            WerrorS("ERROR on binding (no free port available?)");
832            l->data=NULL;
833            omFree(d);
834            return TRUE;
835          }
836        }
837        while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
838        Print("waiting on port %d\n", portno);mflush();
839        listen(sockfd,5);
840        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
841        if(newsockfd < 0)
842        {
843          WerrorS("ERROR on accept");
844          l->data=NULL;
845          omFree(d);
846          return TRUE;
847        }
848        PrintS("client accepted\n");
849        d->fd_read = newsockfd;
850        d->fd_write = newsockfd;
851        d->f_read = s_open(newsockfd);
852        d->f_write = fdopen(newsockfd, "w");
853        SI_LINK_SET_RW_OPEN_P(l);
854        close(sockfd);
855      }
856      // no ssi-Link on stdin or stdout
857      else
858      {
859        Werror("invalid mode >>%s<< for ssi",mode);
860        l->data=NULL;
861        omFree(d);
862        return TRUE;
863      }
864    }
865    // =========================================================================
866    else /*l->name=NULL*/
867    {
868      // tcp mode
869      if(strcmp(mode,"tcp")==0)
870      {
871        int sockfd, newsockfd, portno, clilen;
872        struct sockaddr_in serv_addr, cli_addr;
873        sockfd = socket(AF_INET, SOCK_STREAM, 0);
874        if(sockfd < 0)
875        {
876          WerrorS("ERROR opening socket");
877          l->data=NULL;
878          omFree(d);
879          return TRUE;
880        }
881        memset((char *) &serv_addr,0, sizeof(serv_addr));
882        portno = 1025;
883        serv_addr.sin_family = AF_INET;
884        serv_addr.sin_addr.s_addr = INADDR_ANY;
885        do
886        {
887          portno++;
888          serv_addr.sin_port = htons(portno);
889          if(portno > 50000)
890          {
891            WerrorS("ERROR on binding (no free port available?)");
892            l->data=NULL;
893            return TRUE;
894          }
895        }
896        while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0);
897        //Print("waiting on port %d\n", portno);mflush();
898        listen(sockfd,5);
899        char* cli_host = (char*)omAlloc(256);
900        char* path = (char*)omAlloc(1024);
901        int r = sscanf(l->name,"%255[^:]:%s",cli_host,path);
902        if(r == 0)
903        {
904          WerrorS("ERROR: no host specified");
905          l->data=NULL;
906          omFree(d);
907          omFree(path);
908          omFree(cli_host);
909          return TRUE;
910        }
911        else if(r == 1)
912        {
913          WarnS("program not specified, using /usr/local/bin/Singular");
914          strcpy(path,"/usr/local/bin/Singular");
915        }
916        char* ssh_command = (char*)omAlloc(256);
917        char* ser_host = (char*)omAlloc(64);
918        gethostname(ser_host,64);
919        sprintf(ssh_command,"ssh %s %s -q --batch --link=ssi --MPhost=%s --MPport=%d &",cli_host,path,ser_host,portno);
920        //Print("client on %s started:%s\n",cli_host,path);
921        omFree(path);
922        omFree(cli_host);
923        if (TEST_OPT_PROT) { Print("running >>%s<<\n",ssh_command); }
924        system(ssh_command);
925        omFree(ssh_command);
926        omFree(ser_host);
927        clilen = sizeof(cli_addr);
928        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
929        if(newsockfd < 0)
930        {
931          WerrorS("ERROR on accept");
932          l->data=NULL;
933          omFree(d);
934          return TRUE;
935        }
936        //PrintS("client accepted\n");
937        d->fd_read = newsockfd;
938        d->fd_write = newsockfd;
939        d->f_read = s_open(newsockfd);
940        SSI_BLOCK_CHLD;
941        d->f_write = fdopen(newsockfd, "w");
942        close(sockfd);
943        SSI_UNBLOCK_CHLD;
944        SI_LINK_SET_RW_OPEN_P(l);
945        d->send_quit_at_exit=1;
946        fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,test,verbose);
947      }
948      // ----------------------------------------------------------------------
949      else if(strcmp(mode,"connect")==0)
950      {
951        char* host = (char*)omAlloc(256);
952        int sockfd, portno;
953        struct sockaddr_in serv_addr;
954        struct hostent *server;
955
956        sscanf(l->name,"%255[^:]:%d",host,&portno);
957        //Print("connect to host %s, port %d\n",host,portno);mflush();
958        if (portno!=0)
959        {
960          sockfd = socket(AF_INET, SOCK_STREAM, 0);
961          if (sockfd < 0) { WerrorS("ERROR opening socket"); return TRUE; }
962          server = gethostbyname(host);
963          if (server == NULL) {  WerrorS("ERROR, no such host");  return TRUE; }
964          memset((char *) &serv_addr, 0, sizeof(serv_addr));
965          serv_addr.sin_family = AF_INET;
966          memcpy((char *)&serv_addr.sin_addr.s_addr,
967                (char *)server->h_addr,
968                server->h_length);
969          serv_addr.sin_port = htons(portno);
970          if (connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
971          { Werror("ERROR connecting(errno=%d)",errno); return TRUE; }
972          //PrintS("connected\n");mflush();
973          d->f_read=s_open(sockfd);
974          d->fd_read=sockfd;
975          d->f_write=fdopen(sockfd,"w");
976          d->fd_write=sockfd;
977          SI_LINK_SET_RW_OPEN_P(l);
978          d->send_quit_at_exit=1;
979          omFree(host);
980        }
981        else
982        {
983          l->data=NULL;
984          omFree(d);
985          return TRUE;
986        }
987      }
988      // ======================================================================
989      else
990      {
991        // normal link to a file
992        FILE *outfile;
993        char *filename=l->name;
994
995        if(filename[0]=='>')
996        {
997          if (filename[1]=='>')
998          {
999            filename+=2;
1000            mode = "a";
1001          }
1002          else
1003          {
1004            filename++;
1005            mode="w";
1006          }
1007        }
1008        SSI_BLOCK_CHLD;
1009        outfile=myfopen(filename,mode);
1010        SSI_UNBLOCK_CHLD;
1011        if (outfile!=NULL)
1012        {
1013          if (strcmp(l->mode,"r")==0)
1014          {
1015            SSI_BLOCK_CHLD;
1016            fclose(outfile);
1017            d->f_read=s_open_by_name(filename);
1018            SSI_UNBLOCK_CHLD;
1019          }
1020          else
1021          {
1022            d->f_write = outfile;
1023            fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,test,verbose);
1024          }
1025        }
1026        else
1027        {
1028          omFree(d);
1029          l->data=NULL;
1030          return TRUE;
1031        }
1032      }
1033    }
1034  }
1035
1036  return FALSE;
1037}
1038
1039//**************************************************************************/
1040BOOLEAN ssiClose(si_link l)
1041{
1042  if (l!=NULL)
1043  {
1044    SI_LINK_SET_CLOSE_P(l);
1045    ssiInfo *d = (ssiInfo *)l->data;
1046    if (d!=NULL)
1047    {
1048      if (d->send_quit_at_exit)
1049      {
1050        SSI_BLOCK_CHLD;
1051        fputs("99\n",d->f_write);
1052        fflush(d->f_write);
1053        SSI_UNBLOCK_CHLD;
1054      }
1055      if (d->r!=NULL) rKill(d->r);
1056      if ((d->pid!=0)
1057      && (waitpid(d->pid,NULL,WNOHANG)==0))
1058      {
1059        struct timespec t;
1060        t.tv_sec=0;
1061        t.tv_nsec=50000000; // <=50 ms
1062        int r=nanosleep(&t,NULL);
1063        if((r==0) && (waitpid(d->pid,NULL,WNOHANG)==0))
1064        {
1065          kill(d->pid,15);
1066          t.tv_sec=0;
1067          t.tv_nsec=10000000; // <=10 ms
1068          r=nanosleep(&t,NULL);
1069          if((r==0)&&(waitpid(d->pid,NULL,WNOHANG)==0))
1070          {
1071            kill(d->pid,9); // just to be sure
1072            waitpid(d->pid,NULL,0);
1073          }
1074        }
1075      }
1076      if (d->f_read!=NULL) s_close(d->f_read);
1077      if (d->f_write!=NULL) fclose(d->f_write);
1078      if ((strcmp(l->mode,"tcp")==0)
1079      || (strcmp(l->mode,"fork")==0))
1080      {
1081        link_list hh=ssiToBeClosed;
1082        if (hh!=NULL)
1083        {
1084          if (hh->l==l)
1085          {
1086             ssiToBeClosed=(link_list)hh->next;
1087             omFreeSize(hh,sizeof(link_struct));
1088          }
1089          else while(hh->next!=NULL)
1090          {
1091            link_list hhh=(link_list)hh->next;
1092            if (hhh->l==l)
1093            {
1094              hh->next=hhh->next;
1095              omFreeSize(hhh,sizeof(link_struct));
1096              break;
1097            }
1098            else
1099              hh=(link_list)hh->next;
1100          }
1101        }
1102      }
1103      omFreeSize((ADDRESS)d,(sizeof *d));
1104    }
1105    l->data=NULL;
1106  }
1107  return FALSE;
1108}
1109
1110//**************************************************************************/
1111leftv ssiRead1(si_link l)
1112{
1113  ssiInfo *d = (ssiInfo *)l->data;
1114  leftv res=(leftv)omAlloc0(sizeof(sleftv));
1115  int t=s_readint(d->f_read);
1116  //Print("got type %d\n",t);
1117  switch(t)
1118  {
1119    case 1:res->rtyp=INT_CMD;
1120           res->data=(char *)ssiReadInt(d->f_read);
1121           break;
1122    case 2:res->rtyp=STRING_CMD;
1123           res->data=(char *)ssiReadString(d);
1124           break;
1125    case 3:res->rtyp=NUMBER_CMD;
1126           res->data=(char *)ssiReadNumber(d);
1127           break;
1128    case 4:res->rtyp=BIGINT_CMD;
1129           res->data=(char *)ssiReadBigInt(d);
1130           break;
1131    case 15:
1132    case 5:{
1133             d->r=ssiReadRing(d);
1134             d->r->ref++;
1135             res->rtyp=RING_CMD;
1136             res->data=(char*)d->r;
1137             // we are in the top-level, so set the basering to d->r:
1138             ssiSetCurrRing(d->r);
1139             if (t==15) return ssiRead1(l);
1140           }
1141           break;
1142    case 6:res->rtyp=POLY_CMD;
1143           if (d->r==NULL) goto no_ring;
1144           res->data=(char*)ssiReadPoly(d);
1145           break;
1146    case 7:res->rtyp=IDEAL_CMD;
1147           if (d->r==NULL) goto no_ring;
1148           res->data=(char*)ssiReadIdeal(d);
1149           break;
1150    case 8:res->rtyp=MATRIX_CMD;
1151           if (d->r==NULL) goto no_ring;
1152           res->data=(char*)ssiReadMatrix(d);
1153           break;
1154    case 9:res->rtyp=VECTOR_CMD;
1155           if (d->r==NULL) goto no_ring;
1156           res->data=(char*)ssiReadPoly(d);
1157           break;
1158    case 10:res->rtyp=MODUL_CMD;
1159           if (d->r==NULL) goto no_ring;
1160           res->data=(char*)ssiReadIdeal(d);
1161           break;
1162    case 11:
1163           {
1164             res->rtyp=COMMAND;
1165             res->data=ssiReadCommand(l);
1166             int nok=res->Eval();
1167             if (nok) WerrorS("error in eval");
1168             break;
1169           }
1170    case 12: /*DEF_CMD*/
1171           {
1172             res->rtyp=0;
1173             res->name=(char *)ssiReadString(d);
1174             int nok=res->Eval();
1175             if (nok) WerrorS("error in name lookup");
1176             break;
1177           }
1178    case 13: res->rtyp=PROC_CMD;
1179             res->data=ssiReadProc(d);
1180             break;
1181    case 14: res->rtyp=LIST_CMD;
1182             res->data=ssiReadList(l);
1183             break;
1184    case 16: res->rtyp=NONE; res->data=NULL;
1185             break;
1186    case 17: res->rtyp=INTVEC_CMD;
1187             res->data=ssiReadIntvec(d);
1188             break;
1189    case 18: res->rtyp=INTMAT_CMD;
1190             res->data=ssiReadIntmat(d);
1191             break;
1192    case 20: ssiReadBlackbox(res,l);
1193             break;
1194    // ------------
1195    case 98: // version
1196             {
1197                int n98_v,n98_m;
1198                BITSET n98_o1,n98_o2;
1199                n98_v=s_readint(d->f_read);
1200                n98_m=s_readint(d->f_read);
1201                n98_o1=s_readint(d->f_read);
1202                n98_o2=s_readint(d->f_read);
1203                if ((n98_v!=SSI_VERSION) ||(n98_m!=MAX_TOK))
1204                {
1205                  Print("incompatible versions of ssi: %d/%d vs %d/%d",
1206                                  SSI_VERSION,MAX_TOK,n98_v,n98_m);
1207                }
1208                #ifndef NDEBUG
1209                if (TEST_OPT_DEBUG)
1210                  Print("// opening ssi-%d, MAX_TOK=%d\n",n98_v,n98_m);
1211                #endif
1212                test=n98_o1;
1213                verbose=n98_o2;
1214                return ssiRead1(l);
1215             }
1216    case 99: ssiClose(l); m2_end(0);
1217    case 0: if (s_iseof(d->f_read))
1218            {
1219              ssiClose(l);
1220              res->rtyp=DEF_CMD;
1221              break;
1222            }
1223    default: Werror("not implemented (t:%d)",t);
1224             omFreeSize(res,sizeof(sleftv));
1225             res=NULL;
1226             break;
1227  }
1228  return res;
1229no_ring: WerrorS("no ring");
1230  omFreeSize(res,sizeof(sleftv));
1231  return NULL;
1232}
1233//**************************************************************************/
1234BOOLEAN ssiWrite(si_link l, leftv data)
1235{
1236  if(SI_LINK_W_OPEN_P(l)==0)
1237     if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE;
1238  ssiInfo *d = (ssiInfo *)l->data;
1239  d->level++;
1240  //FILE *fich=d->f;
1241  while (data!=NULL)
1242  {
1243    int tt=data->Typ();
1244    void *dd=data->Data();
1245
1246    switch(tt /*data->Typ()*/)
1247    {
1248          case NONE/* nothing*/:fputs("16 ",d->f_write);
1249                          break;
1250          case STRING_CMD: fputs("2 ",d->f_write);
1251                           ssiWriteString(d,(char *)dd);
1252                           break;
1253          case INT_CMD: fputs("1 ",d->f_write);
1254                        ssiWriteInt(d,(int)(long)dd);
1255                        break;
1256          case BIGINT_CMD:fputs("4 ",d->f_write);
1257                        ssiWriteBigInt(d,(number)dd);
1258                        break;
1259          case NUMBER_CMD:
1260                          if (d->r!=currRing)
1261                          {
1262                            fputs("15 ",d->f_write);
1263                            ssiWriteRing(d,currRing);
1264                            if (d->level<=1) fputc('\n',d->f_write);
1265                          }
1266                          fputs("3 ",d->f_write);
1267                          ssiWriteNumber(d,(number)dd);
1268                        break;
1269          case RING_CMD:fputs("5 ",d->f_write);
1270                        ssiWriteRing(d,(ring)dd);
1271                        break;
1272          case POLY_CMD:
1273          case VECTOR_CMD:
1274                        if (d->r!=currRing)
1275                        {
1276                          fputs("15 ",d->f_write);
1277                          ssiWriteRing(d,currRing);
1278                          if (d->level<=1) fputc('\n',d->f_write);
1279                        }
1280                        if(tt==POLY_CMD) fputs("6 ",d->f_write);
1281                        else             fputs("9 ",d->f_write);
1282                        ssiWritePoly(d,tt,(poly)dd);
1283                        break;
1284          case IDEAL_CMD:
1285          case MODUL_CMD:
1286          case MATRIX_CMD:
1287                        if (d->r!=currRing)
1288                        {
1289                          fputs("15 ",d->f_write);
1290                          ssiWriteRing(d,currRing);
1291                          if (d->level<=1) fputc('\n',d->f_write);
1292                        }
1293                        if(tt==IDEAL_CMD)       fputs("7 ",d->f_write);
1294                        else if(tt==MATRIX_CMD) fputs("8 ",d->f_write);
1295                        else                    fputs("10 ",d->f_write);
1296                        ssiWriteIdeal(d,tt,(ideal)dd);
1297                        break;
1298          case COMMAND:
1299                   fputs("11 ",d->f_write);
1300                   ssiWriteCommand(l,(command)dd);
1301                   break;
1302          case DEF_CMD: /* not evaluated stuff in quotes */
1303                   fputs("12 ",d->f_write);
1304                   ssiWriteString(d,data->Name());
1305                   break;
1306          case PROC_CMD:
1307                   fputs("13 ",d->f_write);
1308                   ssiWriteProc(d,(procinfov)dd);
1309                   break;
1310          case LIST_CMD:
1311                   fputs("14 ",d->f_write);
1312                   ssiWriteList(l,(lists)dd);
1313                   break;
1314          case INTVEC_CMD:
1315                   fputs("17 ",d->f_write);
1316                   ssiWriteIntvec(d,(intvec *)dd);
1317                   break;
1318          case INTMAT_CMD:
1319                   fputs("18 ",d->f_write);
1320                   ssiWriteIntmat(d,(intvec *)dd);
1321                   break;
1322          default:
1323            if (tt>MAX_TOK)
1324            {
1325              blackbox *b=getBlackboxStuff(tt);
1326              fputs("20 ",d->f_write);
1327              b->blackbox_serialize(b,dd,l);
1328            }
1329            else
1330            {
1331              Werror("not implemented (t:%d, rtyp:%d)",tt, data->rtyp);
1332              d->level=0;
1333              return TRUE;
1334            }
1335            break;
1336    }
1337    if (d->level<=1) { fputc('\n',d->f_write); fflush(d->f_write); }
1338    data=data->next;
1339  }
1340  d->level--;
1341  return FALSE;
1342}
1343
1344BOOLEAN ssiGetDump(si_link l);
1345BOOLEAN ssiDump(si_link l);
1346
1347si_link_extension slInitSsiExtension(si_link_extension s)
1348{
1349  s->Open=ssiOpen;
1350  s->Close=ssiClose;
1351  s->Kill=ssiClose;
1352  s->Read=ssiRead1;
1353  s->Read2=(slRead2Proc)NULL;
1354  s->Write=ssiWrite;
1355  s->Dump=ssiDump;
1356  s->GetDump=ssiGetDump;
1357
1358  s->Status=slStatusSsi;
1359  s->type="ssi";
1360  return s;
1361}
1362
1363const char* slStatusSsi(si_link l, const char* request)
1364{
1365  ssiInfo *d=(ssiInfo*)l->data;
1366  if (d==NULL) return "not open";
1367  if (((strcmp(l->mode,"fork")==0)
1368  ||(strcmp(l->mode,"tcp")==0)
1369  ||(strcmp(l->mode,"connect")==0))
1370  && (strcmp(request, "read") == 0))
1371  {
1372    fd_set  mask;
1373    struct timeval wt;
1374    if (s_isready(d->f_read)) return "ready";
1375    loop
1376    {
1377      /* Don't block. Return socket status immediately. */
1378      wt.tv_sec  = 0;
1379      wt.tv_usec = 0;
1380
1381      FD_ZERO(&mask);
1382      FD_SET(d->fd_read, &mask);
1383      //Print("test fd %d\n",d->fd_read);
1384    /* check with select: chars waiting: no -> not ready */
1385      switch (select(d->fd_read+1, &mask, NULL, NULL, &wt))
1386      {
1387        case 0: /* not ready */ return "not ready";
1388        case -1: /*error*/      return "error";
1389        case 1: /*ready ? */    break;
1390      }
1391    /* yes: read 1 char*/
1392    /* if \n, check again with select else ungetc(c), ready*/
1393      int c=s_getc(d->f_read);
1394      //Print("try c=%d\n",c);
1395      if (c== -1) return "eof"; /* eof or error */
1396      else if (isdigit(c))
1397      { s_ungetc(c,d->f_read); return "ready"; }
1398      else if (c>' ')
1399      {
1400        Werror("unknown char in ssiLink(%d)",c);
1401        return "error";
1402      }
1403      /* else: next char */
1404    }
1405  }
1406  else if (strcmp(request, "read") == 0)
1407  {
1408    if (SI_LINK_R_OPEN_P(l) && (!s_iseof(d->f_read)) && (s_isready(d->f_read))) return "ready";
1409    else return "not ready";
1410  }
1411  else if (strcmp(request, "write") == 0)
1412  {
1413    if (SI_LINK_W_OPEN_P(l)) return "ready";
1414    else return "not ready";
1415  }
1416  else return "unknown status request";
1417}
1418
1419int slStatusSsiL(lists L, int timeout)
1420{
1421// input: L: a list with links of type
1422//           ssi-connect, ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch.
1423//           Note: Not every entry in L must be set.
1424//        timeout: timeout for select in micro-seconds
1425//           or -1 for infinity
1426//           or 0 for polling
1427// returns: ERROR (via Werror): L has wrong elements or link not open
1428//           -2: select returns an error
1429//           -1: the read state of all links is eof
1430//           0:  timeout (or polling): none ready,
1431//           i>0: (at least) L[i] is ready
1432  si_link l;
1433  ssiInfo *d;
1434  #ifdef HAVE_MPSR
1435  MP_Link_pt dd;
1436  #endif
1437  int d_fd;
1438  fd_set  mask, fdmask;
1439  FD_ZERO(&fdmask);
1440  FD_ZERO(&mask);
1441  int max_fd=0; /* 1 + max fd in fd_set */
1442
1443  /* timeout */
1444  #ifdef HAVE_PSELECT
1445  struct timespec wt;
1446  struct timespec *wt_ptr=&wt;
1447  #else
1448  struct timeval wt;
1449  struct timeval *wt_ptr=&wt;
1450  #endif
1451  int startingtime = getRTimer()/TIMER_RESOLUTION;  // in seconds
1452  if (timeout== -1)
1453  {
1454    wt_ptr=NULL;
1455  }
1456  else
1457  {
1458    wt.tv_sec  = timeout / 1000000;
1459  #ifdef HAVE_PSELECT
1460    wt.tv_nsec = 1000 * (timeout % 1000000);
1461  #else
1462    wt.tv_usec = timeout % 1000000;
1463  #endif
1464  }
1465
1466  /* signal mask for pselect() */
1467  sigset_t sigmask;
1468  if(sigprocmask(SIG_SETMASK, NULL, &sigmask) < 0)
1469  {
1470    WerrorS("error in sigprocmask()");
1471    return -2;
1472  }
1473  if(sigaddset(&sigmask, SIGCHLD) < 0)
1474  {
1475    WerrorS("error in sigaddset()");
1476    return -2;
1477  }
1478
1479  /* auxiliary variables */
1480  int i;
1481  int j;
1482  int k;
1483  int s;
1484  char fdmaskempty;
1485
1486  /* check the links and fill in fdmask */
1487  /* check ssi links for ungetc_buf */
1488  for(i=L->nr; i>=0; i--)
1489  {
1490    if (L->m[i].Typ()!=DEF_CMD)
1491    {
1492      if (L->m[i].Typ()!=LINK_CMD)
1493      { WerrorS("all elements must be of type link"); return -2;}
1494      l=(si_link)L->m[i].Data();
1495      if(SI_LINK_OPEN_P(l)==0)
1496      { WerrorS("all links must be open"); return -2;}
1497      if (((strcmp(l->m->type,"ssi")!=0) && (strcmp(l->m->type,"MPtcp")!=0))
1498      || ((strcmp(l->mode,"fork")!=0) && (strcmp(l->mode,"tcp")!=0)
1499        && (strcmp(l->mode,"launch")!=0) && (strcmp(l->mode,"connect")!=0)))
1500      {
1501        WerrorS("all links must be of type ssi:fork, ssi:tcp, ssi:connect,");
1502        WerrorS(" MPtcp:fork or MPtcp:launch");
1503        return -2;
1504      }
1505    #ifdef HAVE_MPSR
1506      if (strcmp(l->m->type,"ssi")==0)
1507      {
1508        d=(ssiInfo*)l->data;
1509        d_fd=d->fd_read;
1510        if (!s_isready(d->f_read))
1511        {
1512          FD_SET(d_fd, &fdmask);
1513          if (d_fd > max_fd) max_fd=d_fd;
1514        }
1515        else
1516          return i+1;
1517      }
1518      else
1519      {
1520        dd=(MP_Link_pt)l->data;
1521        d_fd=((MP_TCP_t *)dd->transp.private1)->sock;
1522        FD_SET(d_fd, &fdmask);
1523        if (d_fd > max_fd) max_fd=d_fd;
1524      }
1525    #else
1526      d=(ssiInfo*)l->data;
1527      d_fd=d->fd_read;
1528      if (!s_isready(d->f_read))
1529      {
1530        FD_SET(d_fd, &fdmask);
1531        if (d_fd > max_fd) max_fd=d_fd;
1532      }
1533      else
1534        return i+1;
1535    #endif
1536    }
1537  }
1538  max_fd++;
1539
1540do_select:
1541  /* copy fdmask to mask */
1542  FD_ZERO(&mask);
1543  for(k = 0; k < max_fd; k++)
1544  {
1545    if(FD_ISSET(k, &fdmask))
1546    {
1547      FD_SET(k, &mask);
1548    }
1549  }
1550
1551  /* check with select: chars waiting: no -> not ready */
1552  #ifdef HAVE_SIMPLEIPC
1553  sipc_semaphore_release(0);
1554  #endif
1555  #ifdef HAVE_PSELECT
1556  s = pselect(max_fd, &mask, NULL, NULL, wt_ptr, &sigmask);
1557  #else
1558  SSI_BLOCK_CHLD;
1559  s = select(max_fd, &mask, NULL, NULL, wt_ptr);
1560  SSI_UNBLOCK_CHLD;
1561  #endif
1562  #ifdef HAVE_SIMPLEIPC
1563  sipc_semaphore_acquire(0);
1564  #endif
1565
1566  if (s==-1)
1567  {
1568    WerrorS("error in select call");
1569    return -2; /*error*/
1570  }
1571  if (s==0)
1572  {
1573    return 0; /*poll: not ready */
1574  }
1575  else /* s>0, at least one ready  (the number of fd which are ready is s)*/
1576  {
1577    j=0;
1578    while (j<=max_fd) { if (FD_ISSET(j,&mask)) break; j++; }
1579    for(i=L->nr; i>=0; i--)
1580    {
1581      if (L->m[i].rtyp==LINK_CMD)
1582      {
1583        l=(si_link)L->m[i].Data();
1584        #ifdef HAVE_MPSR
1585        if (strcmp(l->m->type,"ssi")!=0)
1586        {
1587          // for MP links, return here:
1588          dd=(MP_Link_pt)l->data;
1589          d_fd=((MP_TCP_t *)dd->transp.private1)->sock;
1590          if(j==d_fd) return i+1;
1591        }
1592        else
1593        {
1594          d=(ssiInfo*)l->data;
1595          d_fd=d->fd_read;
1596          if(j==d_fd) break;
1597        }
1598        #else
1599        d=(ssiInfo*)l->data;
1600        d_fd=d->fd_read;
1601        if(j==d_fd) break;
1602        #endif
1603      }
1604    }
1605    // only ssi links:
1606    loop
1607    {
1608      /* yes: read 1 char*/
1609      /* if \n, check again with select else ungetc(c), ready*/
1610      /* setting: d: current ssiInfo, j current fd, i current entry in L*/
1611      int c=s_getc(d->f_read);
1612      //Print("try c=%d\n",c);
1613      if (c== -1) /* eof */
1614      {
1615        FD_CLR(j,&fdmask);
1616        fdmaskempty = 1;
1617        for(k = 0; k < max_fd; k++)
1618        {
1619          if(FD_ISSET(k, &fdmask))
1620          {
1621            fdmaskempty = 0;
1622            break;
1623          }
1624        }
1625        if(fdmaskempty)
1626        {
1627          return -1;
1628        }
1629        if(timeout != -1)
1630        {
1631          timeout = si_max(0,
1632             timeout - 1000000*(getRTimer()/TIMER_RESOLUTION - startingtime));
1633          wt.tv_sec  = timeout / 1000000;
1634          #ifdef HAVE_PSELECT
1635          wt.tv_nsec = 1000 * (timeout % 1000000);
1636          #else
1637          wt.tv_usec = (timeout % 1000000);
1638          #endif
1639        }
1640        goto do_select;
1641      }
1642
1643      else if (isdigit(c))
1644      { s_ungetc(c,d->f_read); return i+1; }
1645      else if (c>' ')
1646      {
1647        Werror("unknown char in ssiLink(%d)",c);
1648        return -2;
1649      }
1650      /* else: next char */
1651    }
1652  }
1653}
1654
1655int ssiBatch(const char *host, const char * port)
1656/* return 0 on success, >0 else*/
1657{
1658  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1659  char *buf=(char*)omAlloc(256);
1660  sprintf(buf,"ssi:connect %s:%s",host,port);
1661  slInit(l, buf);
1662  if (slOpen(l,SI_LINK_OPEN,NULL)) return 1;
1663  SI_LINK_SET_RW_OPEN_P(l);
1664
1665  idhdl id = enterid(omStrDup("link_ll"), 0, LINK_CMD, &IDROOT, FALSE);
1666  IDLINK(id) = l;
1667
1668  loop
1669  {
1670    leftv h=ssiRead1(l); /*contains an exit.... */
1671    if (feErrors != NULL && *feErrors != '\0')
1672    {
1673      // handle errors:
1674      PrintS(feErrors); /* currently quite simple */
1675      *feErrors = '\0';
1676    }
1677    ssiWrite(l,h);
1678    h->CleanUp();
1679    omFreeBin(h, sleftv_bin);
1680  }
1681  /* never reached*/
1682  exit(0);
1683}
1684
1685static int ssiReserved_P=0;
1686static int ssiReserved_sockfd;
1687static  struct sockaddr_in ssiResverd_serv_addr;
1688static int  ssiReserved_Clients;
1689int ssiReservePort(int clients)
1690{
1691  if (ssiReserved_P!=0)
1692  {
1693    WerrorS("ERROR already a reverved port requested");
1694    return 0;
1695  }
1696  int portno;
1697  ssiReserved_sockfd = socket(AF_INET, SOCK_STREAM, 0);
1698  if(ssiReserved_sockfd < 0)
1699  {
1700    WerrorS("ERROR opening socket");
1701    return 0;
1702  }
1703  memset((char *) &ssiResverd_serv_addr,0, sizeof(ssiResverd_serv_addr));
1704  portno = 1025;
1705  ssiResverd_serv_addr.sin_family = AF_INET;
1706  ssiResverd_serv_addr.sin_addr.s_addr = INADDR_ANY;
1707  do
1708  {
1709    portno++;
1710    ssiResverd_serv_addr.sin_port = htons(portno);
1711    if(portno > 50000)
1712    {
1713      WerrorS("ERROR on binding (no free port available?)");
1714      return 0;
1715    }
1716  }
1717  while(bind(ssiReserved_sockfd, (struct sockaddr *) &ssiResverd_serv_addr, sizeof(ssiResverd_serv_addr)) < 0);
1718  ssiReserved_P=portno;
1719  listen(ssiReserved_sockfd,clients);
1720  ssiReserved_Clients=clients;
1721  return portno;
1722}
1723
1724extern si_link_extension si_link_root;
1725si_link ssiCommandLink()
1726{
1727  if (ssiReserved_P==0)
1728  {
1729    WerrorS("ERROR no reverved port requested");
1730    return NULL;
1731  }
1732  struct sockaddr_in cli_addr;
1733  int clilen = sizeof(cli_addr);
1734  int newsockfd = accept(ssiReserved_sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen);
1735  if(newsockfd < 0)
1736  {
1737    Werror("ERROR on accept (errno=%d)",errno);
1738    return NULL;
1739  }
1740  si_link l=(si_link) omAlloc0Bin(sip_link_bin);
1741  si_link_extension s = si_link_root;
1742  si_link_extension prev = s;
1743  while (strcmp(s->type, "ssi") != 0)
1744  {
1745    if (s->next == NULL)
1746    {
1747      prev = s;
1748      s = NULL;
1749      break;
1750    }
1751    else
1752    {
1753      s = s->next;
1754    }
1755  }
1756  if (s != NULL)
1757    l->m = s;
1758  else
1759  {
1760    si_link_extension ns = (si_link_extension)omAlloc0Bin(s_si_link_extension_bin);
1761    prev->next=slInitSsiExtension(ns);
1762    l->m = prev->next;
1763  }
1764  l->name=omStrDup("");
1765  l->mode=omStrDup("tcp");
1766  l->ref=1;
1767  ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo));
1768  sigprocmask(SIG_SETMASK, NULL, &ssi_sigmask);
1769  sigaddset(&ssi_sigmask, SIGCHLD);
1770  l->data=d;
1771  d->fd_read = newsockfd;
1772  d->fd_write = newsockfd;
1773  d->f_read = s_open(newsockfd);
1774  d->f_write = fdopen(newsockfd, "w");
1775  SI_LINK_SET_RW_OPEN_P(l);
1776  ssiReserved_Clients--;
1777  if (ssiReserved_Clients<=0)
1778  {
1779    ssiReserved_P=0;
1780    close(ssiReserved_sockfd);
1781  }
1782  return l;
1783}
1784/*---------------------------------------------------------------------*/
1785/**
1786 * @brief additional default signal handler
1787
1788  // some newer Linux version cannot have SIG_IGN for SIGCHLD,
1789  // so use this nice routine here:
1790  //  SuSe 9.x reports -1 always
1791  //  Redhat 9.x/FC x reports sometimes -1
1792  // see also: hpux_system
1793  // also needed by getrusage (timer etc.)
1794
1795 @param[in] sig
1796**/
1797/*---------------------------------------------------------------------*/
1798void sig_chld_hdl(int sig)
1799{
1800  pid_t kidpid;
1801  int status;
1802
1803  loop
1804  {
1805    kidpid = waitpid(-1, &status, WNOHANG);
1806    if (kidpid==-1)
1807    {
1808      /* continue on interruption (EINTR): */
1809      if (errno == EINTR) continue;
1810      /* break on anything else (EINVAL or ECHILD according to manpage): */
1811      break;
1812    }
1813    else if (kidpid==0) break; /* no more children to process, so break */
1814
1815    //printf("Child %ld terminated\n", kidpid);
1816    link_list hh=ssiToBeClosed;
1817    while(hh!=NULL)
1818    {
1819      if((hh->l!=NULL) && (hh->l->m->Open==ssiOpen))
1820      {
1821        ssiInfo *d = (ssiInfo *)hh->l->data;
1822        if(d->pid==kidpid)
1823        {
1824          if(ssiToBeClosed_inactive)
1825          {
1826            ssiToBeClosed_inactive=FALSE;
1827            slClose(hh->l);
1828            ssiToBeClosed_inactive=TRUE;
1829            break;
1830          }
1831          else break;
1832        }
1833        else hh=(link_list)hh->next;
1834      }
1835      else hh=(link_list)hh->next;
1836    }
1837  }
1838}
1839
1840static BOOLEAN DumpSsiIdhdl(si_link l, idhdl h)
1841{
1842  int type_id = IDTYP(h);
1843
1844  // C-proc not to be dumped, also LIB-proc not
1845  if (type_id == PROC_CMD)
1846  {
1847    if (IDPROC(h)->language == LANG_C) return FALSE;
1848    if (IDPROC(h)->libname != NULL) return FALSE;
1849  }
1850  // do not dump links
1851  if (type_id == LINK_CMD) return FALSE;
1852
1853  // do not dump ssi internal rings: ssiRing*
1854  if ((type_id == RING_CMD) && (strncmp(IDID(h),"ssiRing",7)==0))
1855    return FALSE;
1856
1857  command D=(command)omAlloc0(sizeof(*D));
1858  sleftv tmp;
1859  memset(&tmp,0,sizeof(tmp));
1860  tmp.rtyp=COMMAND;
1861  tmp.data=D;
1862
1863  if (type_id == PACKAGE_CMD)
1864  {
1865    // do not dump Top
1866    if (strcmp(IDID(h), "Top") == 0) return FALSE;
1867    package p=(package)IDDATA(h);
1868    // dump Singular-packages as load("...");
1869    if (p->language==LANG_SINGULAR)
1870    {
1871      D->op=LOAD_CMD;
1872      D->argc=1;
1873      D->arg1.rtyp=STRING_CMD;
1874      D->arg1.data=p->libname;
1875      ssiWrite(l,&tmp);
1876      omFree(D);
1877      return FALSE;
1878    }
1879  }
1880
1881  // handle qrings separately
1882  //if (type_id == QRING_CMD)
1883  //  return DumpSsiQringQring(l, h);
1884
1885  // put type and name
1886  //Print("generic dump:%s,%s\n",IDID(h),Tok2Cmdname(IDTYP(h)));
1887  D->op='=';
1888  D->argc=2;
1889  D->arg1.rtyp=DEF_CMD;
1890  D->arg1.name=IDID(h);
1891  D->arg2.rtyp=IDTYP(h);
1892  D->arg2.data=IDDATA(h);
1893  ssiWrite(l,&tmp);
1894  omFree(D);
1895  return FALSE;
1896}
1897static BOOLEAN ssiDumpIter(si_link l, idhdl h)
1898{
1899  if (h == NULL) return FALSE;
1900
1901  if (ssiDumpIter(l, IDNEXT(h))) return TRUE;
1902
1903  // need to set the ring before writing it, otherwise we get in
1904  // trouble with minpoly
1905  if (IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD)
1906    rSetHdl(h);
1907
1908  if (DumpSsiIdhdl(l, h)) return TRUE;
1909
1910  // do not dump ssi internal rings: ssiRing*
1911  // but dump objects of all other rings
1912  if ((IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD)
1913  && (strncmp(IDID(h),"ssiRing",7)!=0))
1914    return ssiDumpIter(l, IDRING(h)->idroot);
1915  else
1916    return FALSE;
1917}
1918BOOLEAN ssiDump(si_link l)
1919{
1920  idhdl h = IDROOT, rh = currRingHdl;
1921  BOOLEAN status = ssiDumpIter(l, h);
1922
1923  //if (! status ) status = DumpAsciiMaps(fd, h, NULL);
1924
1925  if (currRingHdl != rh) rSetHdl(rh);
1926  //fprintf(fd, "option(set, intvec(%d, %d));\n", test, verbose);
1927
1928  return status;
1929}
1930BOOLEAN ssiGetDump(si_link l)
1931{
1932  ssiInfo *d=(ssiInfo*)l->data;
1933  loop
1934  {
1935    if (!SI_LINK_OPEN_P(l)) break;
1936    if (s_iseof(d->f_read)) break;
1937    leftv h=ssiRead1(l); /*contains an exit.... */
1938    if (feErrors != NULL && *feErrors != '\0')
1939    {
1940      // handle errors:
1941      PrintS(feErrors); /* currently quite simple */
1942      return TRUE;
1943      *feErrors = '\0';
1944    }
1945    h->CleanUp();
1946    omFreeBin(h, sleftv_bin);
1947  }
1948  return FALSE;
1949}
1950// ----------------------------------------------------------------
1951// format
1952// 1 int %d
1953// 2 string <len> %s
1954// 3 number
1955// 4 bigint 4 %d or 3 <mpz_t>
1956// 5 ring
1957// 6 poly
1958// 7 ideal
1959// 8 matrix
1960// 9 vector
1961// 10 module
1962// 11 command
1963// 12 def <len> %s
1964// 13 proc <len> %s
1965// 14 list %d <elem1> ....
1966// 15 setring .......
1967// 16 nothing
1968// 17 intvec <len> ...
1969// 18 intmat
1970//
1971// 20 blackbox <name> ...
1972//
1973// 98: verify version: <ssi-version> <MAX_TOK> <OPT1> <OPT2>
1974// 99: quit Singular
Note: See TracBrowser for help on using the repository browser.