[4082e8] | 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" |
---|
[b1dfaf] | 24 | #include <omalloc/omalloc.h> |
---|
[4082e8] | 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 | //**************************************************************************/ |
---|
[b5f276e] | 40 | BOOLEAN pipeOpen(si_link l, short flag, leftv u) |
---|
[4082e8] | 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 | { |
---|
[b5f276e] | 130 | if(!SI_LINK_W_OPEN_P(l)) slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL); |
---|
[4082e8] | 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"; |
---|
[e56bbf] | 184 | default: /*1: ready ? */return "ready"; |
---|
[4082e8] | 185 | } |
---|
| 186 | } |
---|
| 187 | else if (strcmp(request, "write") == 0) |
---|
| 188 | { |
---|
| 189 | if (SI_LINK_W_OPEN_P(l)) return "ready"; |
---|
[e56bbf] | 190 | return "not ready"; |
---|
[4082e8] | 191 | } |
---|
[e56bbf] | 192 | return "unknown status request"; |
---|
[4082e8] | 193 | } |
---|
| 194 | |
---|
| 195 | si_link_extension slInitPipeExtension(si_link_extension s) |
---|
| 196 | { |
---|
[b5f276e] | 197 | s->Open=pipeOpen; |
---|
| 198 | s->Close=pipeClose; |
---|
| 199 | s->Kill=pipeKill; |
---|
| 200 | s->Read=pipeRead1; |
---|
[4082e8] | 201 | s->Read2=(slRead2Proc)NULL; |
---|
[b5f276e] | 202 | s->Write=pipeWrite; |
---|
[4082e8] | 203 | |
---|
| 204 | s->Status=slStatusPipe; |
---|
| 205 | s->type="pipe"; |
---|
| 206 | return s; |
---|
| 207 | } |
---|