source: git/Singular/links/ssiLink.cc @ 3631a1

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