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 "config.h" |
---|
21 | #include <kernel/mod2.h> |
---|
22 | |
---|
23 | #include "tok.h" |
---|
24 | #include "ipid.h" |
---|
25 | #include <omalloc/omalloc.h> |
---|
26 | #include "subexpr.h" |
---|
27 | #include "silink.h" |
---|
28 | #include "lists.h" |
---|
29 | #include "pipeLink.h" |
---|
30 | |
---|
31 | typedef 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 | //**************************************************************************/ |
---|
41 | BOOLEAN 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 | close(pc[1]); close(cp[0]); |
---|
57 | /* dup pipe read/write to stdin/stdout */ |
---|
58 | dup2( pc[0], STDIN_FILENO ); |
---|
59 | dup2( cp[1], STDOUT_FILENO ); |
---|
60 | int r=system(l->name); |
---|
61 | close(pc[0]); |
---|
62 | close(cp[1]); |
---|
63 | exit(r); |
---|
64 | /* never reached*/ |
---|
65 | } |
---|
66 | else if (pid>0) |
---|
67 | { |
---|
68 | d->pid=pid; |
---|
69 | close(pc[0]); 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 | //**************************************************************************/ |
---|
87 | LINKAGE BOOLEAN pipeClose(si_link l) |
---|
88 | { |
---|
89 | pipeInfo *d = (pipeInfo *)l->data; |
---|
90 | if (d!=NULL) |
---|
91 | { |
---|
92 | if (d->f_read!=NULL) fclose(d->f_read); |
---|
93 | if (d->f_write!=NULL) fclose(d->f_write); |
---|
94 | if (d->pid!=0) { kill(d->pid,15); kill(d->pid,9); } |
---|
95 | } |
---|
96 | SI_LINK_SET_CLOSE_P(l); |
---|
97 | return FALSE; |
---|
98 | } |
---|
99 | |
---|
100 | //**************************************************************************/ |
---|
101 | LINKAGE BOOLEAN pipeKill(si_link l) |
---|
102 | { |
---|
103 | if(SI_LINK_OPEN_P(l)) pipeClose(l); |
---|
104 | pipeInfo *d = (pipeInfo *)l->data; |
---|
105 | if (d!=NULL) |
---|
106 | { |
---|
107 | omFreeSize((ADDRESS)d,(sizeof *d)); |
---|
108 | } |
---|
109 | l->data=NULL; |
---|
110 | return FALSE; |
---|
111 | } |
---|
112 | |
---|
113 | //**************************************************************************/ |
---|
114 | LINKAGE leftv pipeRead1(si_link l) |
---|
115 | { |
---|
116 | pipeInfo *d = (pipeInfo *)l->data; |
---|
117 | leftv res=(leftv)omAlloc0(sizeof(sleftv)); |
---|
118 | char *s=(char *)omAlloc0(1024); |
---|
119 | char *ss=fgets(s,1024,d->f_read); |
---|
120 | if (ss==NULL) { omFreeSize(s,1024); pipeClose(l);return NULL; } |
---|
121 | int i=strlen(s)-1; |
---|
122 | if ((i>=0) && (s[i]=='\n')) s[i]='\0'; |
---|
123 | res->rtyp=STRING_CMD; |
---|
124 | res->data=s; |
---|
125 | return res; |
---|
126 | } |
---|
127 | //**************************************************************************/ |
---|
128 | extern si_link pipeLastLink; |
---|
129 | LINKAGE BOOLEAN pipeWrite(si_link l, leftv data) |
---|
130 | { |
---|
131 | if(!SI_LINK_W_OPEN_P(l)) slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL); |
---|
132 | pipeInfo *d = (pipeInfo *)l->data; |
---|
133 | FILE *outfile=d->f_write;; |
---|
134 | BOOLEAN err=FALSE; |
---|
135 | char *s; |
---|
136 | pipeLastLink=l; |
---|
137 | while (data!=NULL) |
---|
138 | { |
---|
139 | s = data->String(); |
---|
140 | // free data ?? |
---|
141 | if (s!=NULL) |
---|
142 | { |
---|
143 | fprintf(outfile,"%s\n",s); |
---|
144 | omFree((ADDRESS)s); |
---|
145 | } |
---|
146 | else |
---|
147 | { |
---|
148 | Werror("cannot convert to string"); |
---|
149 | err=TRUE; |
---|
150 | } |
---|
151 | if (pipeLastLink==NULL) return TRUE; |
---|
152 | data = data->next; |
---|
153 | } |
---|
154 | fflush(outfile); |
---|
155 | pipeLastLink=NULL; |
---|
156 | return err; |
---|
157 | } |
---|
158 | |
---|
159 | const char* slStatusPipe(si_link l, const char* request) |
---|
160 | { |
---|
161 | pipeInfo *d=(pipeInfo*)l->data; |
---|
162 | if (d==NULL) return "not open"; |
---|
163 | if(strcmp(request, "read") == 0) |
---|
164 | { |
---|
165 | int s; |
---|
166 | if ((!SI_LINK_R_OPEN_P(l)) || (feof(d->f_read))) s=0; |
---|
167 | else |
---|
168 | { |
---|
169 | fd_set mask, fdmask; |
---|
170 | struct timeval wt; |
---|
171 | /* Don't block. Return socket status immediately. */ |
---|
172 | wt.tv_sec = 0; |
---|
173 | wt.tv_usec = 0; |
---|
174 | |
---|
175 | FD_ZERO(&mask); |
---|
176 | FD_SET(d->fd_read, &mask); |
---|
177 | //Print("test fd %d\n",d->fd_read); |
---|
178 | /* check with select: chars waiting: no -> not ready */ |
---|
179 | s=select(d->fd_read+1, &mask, NULL, NULL, &wt); |
---|
180 | } |
---|
181 | switch (s) |
---|
182 | { |
---|
183 | case 0: /* not ready */ return "not ready"; |
---|
184 | case -1: /*error*/ return "error"; |
---|
185 | default: /*1: ready ? */return "ready"; |
---|
186 | } |
---|
187 | } |
---|
188 | else if (strcmp(request, "write") == 0) |
---|
189 | { |
---|
190 | if (SI_LINK_W_OPEN_P(l)) return "ready"; |
---|
191 | return "not ready"; |
---|
192 | } |
---|
193 | return "unknown status request"; |
---|
194 | } |
---|
195 | |
---|
196 | si_link_extension slInitPipeExtension(si_link_extension s) |
---|
197 | { |
---|
198 | s->Open=pipeOpen; |
---|
199 | s->Close=pipeClose; |
---|
200 | s->Kill=pipeKill; |
---|
201 | s->Read=pipeRead1; |
---|
202 | s->Read2=(slRead2Proc)NULL; |
---|
203 | s->Write=pipeWrite; |
---|
204 | |
---|
205 | s->Status=slStatusPipe; |
---|
206 | s->type="pipe"; |
---|
207 | return s; |
---|
208 | } |
---|