source: git/Singular/links/pipeLink.cc @ e02d34

fieker-DuValspielwiese
Last change on this file since e02d34 was e02d34, checked in by Hans Schoenemann <hannes@…>, 6 years ago
add: close of bidirect. pipe link: close write only
  • Property mode set to 100644
File size: 5.2 KB
Line 
1/****************************************
2 * Computer Algebra System SINGULAR     *
3 ****************************************/
4/***************************************************************
5 * File:    pipeLink.h
6 *  Purpose: declaration of sl_link routines for pipe
7 ***************************************************************/
8
9#include "kernel/mod2.h"
10
11#include "omalloc/omalloc.h"
12#include "reporter/si_signals.h"
13
14#include "tok.h"
15#include "ipid.h"
16#include "subexpr.h"
17#include "links/silink.h"
18#include "lists.h"
19#include "pipeLink.h"
20
21#include <stdio.h>
22#include <fcntl.h>
23#include <errno.h>
24#include <unistd.h>
25#include <sys/types.h>
26#include <signal.h>
27#include <sys/types.h>          /* for portability */
28#include <sys/select.h>
29#include <sys/socket.h>
30
31typedef struct
32{
33  FILE *f_read;
34  FILE *f_write;
35  pid_t pid; /* only valid for fork/tcp mode*/
36  int fd_read,fd_write; /* only valid for fork/tcp mode*/
37  char level;
38} pipeInfo;
39
40//**************************************************************************/
41BOOLEAN pipeOpen(si_link l, short flag, leftv /*u*/)
42{
43  pipeInfo *d=(pipeInfo*)omAlloc0(sizeof(pipeInfo));
44  if (flag & SI_LINK_OPEN)
45  {
46      flag = SI_LINK_READ| SI_LINK_WRITE;
47  }
48  int pc[2];
49  int cp[2];
50  pipe(pc);
51  pipe(cp);
52  pid_t pid=fork();
53  if (pid==0) /*child*/
54  {
55    /* close unnecessary pipe descriptors for a clean environment */
56    si_close(pc[1]); si_close(cp[0]);
57    /* dup pipe read/write to stdin/stdout */
58    si_dup2( pc[0], STDIN_FILENO );
59    si_dup2( cp[1], STDOUT_FILENO  );
60    int r=system(l->name);
61    si_close(pc[0]);
62    si_close(cp[1]);
63    exit(r);
64        /* never reached*/
65  }
66  else if (pid>0)
67  {
68    d->pid=pid;
69    si_close(pc[0]); si_close(cp[1]);
70    d->f_read=fdopen(cp[0],"r");
71    d->fd_read=cp[0];
72    d->f_write=fdopen(pc[1],"w");
73    d->fd_write=pc[1];
74    SI_LINK_SET_RW_OPEN_P(l);
75  }
76  else
77  {
78    Werror("fork failed (%d)",errno);
79    omFreeSize(d,sizeof(*d));
80    return TRUE;
81  }
82  l->data=d;
83  return FALSE;
84}
85
86//**************************************************************************/
87LINKAGE BOOLEAN pipeClose(si_link l)
88{
89  pipeInfo *d = (pipeInfo *)l->data;
90  if (d!=NULL)
91  {
92    BOOLEAN unidirectional=TRUE;
93    if ( (d->f_read!=NULL) &&  (d->f_write!=NULL))
94      unidirectional=FALSE;
95
96    if (d->f_read!=NULL)
97    {
98      fclose(d->f_read);
99      d->f_read=NULL;
100      SI_LINK_SET_CLOSE_P(l);
101      SI_LINK_SET_R_OPEN_P(l);
102    }
103    if (unidirectional && (d->f_write!=NULL))
104    {
105      fclose(d->f_write);
106      d->f_write=NULL;
107      SI_LINK_SET_CLOSE_P(l);
108    }
109    if (unidirectional && (d->pid!=0))
110    { kill(d->pid,15); kill(d->pid,9); }
111  }
112  else SI_LINK_SET_CLOSE_P(l);
113  return FALSE;
114}
115
116//**************************************************************************/
117LINKAGE BOOLEAN pipeKill(si_link l)
118{
119  if(SI_LINK_OPEN_P(l)) pipeClose(l);
120  pipeInfo *d = (pipeInfo *)l->data;
121  if (d!=NULL)
122  {
123    omFreeSize((ADDRESS)d,(sizeof *d));
124  }
125  l->data=NULL;
126  return FALSE;
127}
128
129//**************************************************************************/
130LINKAGE leftv pipeRead1(si_link l)
131{
132  pipeInfo *d = (pipeInfo *)l->data;
133  leftv res=(leftv)omAlloc0(sizeof(sleftv));
134  char *s=(char *)omAlloc0(1024);
135  char *ss=fgets(s,1024,d->f_read);
136  if (ss==NULL) { omFreeSize(s,1024); pipeClose(l);return NULL; }
137  int i=strlen(s)-1;
138  if ((i>=0) && (s[i]=='\n')) s[i]='\0';
139  res->rtyp=STRING_CMD;
140  res->data=s;
141  return res;
142}
143//**************************************************************************/
144extern si_link pipeLastLink;
145LINKAGE BOOLEAN pipeWrite(si_link l, leftv data)
146{
147  if(!SI_LINK_W_OPEN_P(l)) slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL);
148  pipeInfo *d = (pipeInfo *)l->data;
149  FILE *outfile=d->f_write;;
150  BOOLEAN err=FALSE;
151  char *s;
152  pipeLastLink=l;
153  while (data!=NULL)
154  {
155    s = data->String();
156    // free data ??
157    if (s!=NULL)
158    {
159      fprintf(outfile,"%s\n",s);
160      omFree((ADDRESS)s);
161    }
162    else
163    {
164      WerrorS("cannot convert to string");
165      err=TRUE;
166    }
167    if (pipeLastLink==NULL) return TRUE;
168    data = data->next;
169  }
170  fflush(outfile);
171  pipeLastLink=NULL;
172  return err;
173}
174
175const char* slStatusPipe(si_link l, const char* request)
176{
177  pipeInfo *d=(pipeInfo*)l->data;
178  if (d==NULL) return "not open";
179  if(strcmp(request, "read") == 0)
180  {
181    int s;
182    if ((!SI_LINK_R_OPEN_P(l)) || (feof(d->f_read))) s=0;
183    else
184    {
185      fd_set  mask/*, fdmask*/;
186      struct timeval wt;
187      /* Don't block. Return socket status immediately. */
188      wt.tv_sec  = 0;
189      wt.tv_usec = 0;
190
191      FD_ZERO(&mask);
192      FD_SET(d->fd_read, &mask);
193      //Print("test fd %d\n",d->fd_read);
194      /* check with select: chars waiting: no -> not ready */
195      s=si_select(d->fd_read+1, &mask, NULL, NULL, &wt);
196    }
197    switch (s)
198    {
199      case 0: /* not ready */ return "not ready";
200      case -1: /*error*/      return "error";
201      default: /*1: ready ? */return "ready";
202    }
203  }
204  else if (strcmp(request, "write") == 0)
205  {
206    if (SI_LINK_W_OPEN_P(l)) return "ready";
207    return "not ready";
208  }
209  return "unknown status request";
210}
211
212si_link_extension slInitPipeExtension(si_link_extension s)
213{
214  s->Open=pipeOpen;
215  s->Close=pipeClose;
216  s->Kill=pipeKill;
217  s->Read=pipeRead1;
218  s->Read2=(slRead2Proc)NULL;
219  s->Write=pipeWrite;
220
221  s->Status=slStatusPipe;
222  s->type="pipe";
223  return s;
224}
Note: See TracBrowser for help on using the repository browser.