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