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