source: git/Singular/links/ssiLink.cc @ 44ca2f

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