source: git/Singular/links/pipeLink.cc @ 16f511

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