Fixed HTTP-client query-string handling bug.
[doldaconnect.git] / clients / gnome-trans-applet / conduit-pipe.c
CommitLineData
d3372da9 1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4#include <string.h>
5#include <unistd.h>
6#include <stdlib.h>
7#include <stdio.h>
8#include <errno.h>
9#include <signal.h>
10#include <fcntl.h>
11#include <panel-applet.h>
12#include <doldaconnect/utils.h>
13
14#include "conduit.h"
15
16#define SUBPROCCMD "ksu fredrik -q -e /home/fredrik/bin/dctrmon"
17
18struct data
19{
20 pid_t subproc;
21 int fd;
22 int gdktag;
23 char *inbuf;
24 size_t inbufsize, inbufdata;
25};
26
27static void pipefdcb(struct conduit *conduit, int fd, GdkInputCondition condition)
28{
29 struct data *data;
30 int ret;
31 char *p, *p2, *cmd;
32 char **args;
33 size_t argssize, argsdata;
34 struct transfer *transfer;
35
36 data = (struct data *)conduit->cdata;
37 if(conduit->state == CNDS_SYN)
38 condconnected(conduit);
39 sizebuf2(data->inbuf, data->inbufdata + 80, 1);
40 ret = read(data->fd, data->inbuf + data->inbufdata, data->inbufsize - data->inbufdata);
41 if(ret < 0)
42 {
43 if((errno == EINTR) || (errno == EAGAIN)) /* Shouldn't happen, but, oh well... */
44 return;
45 perror("conduit-pipe: read");
46 gdk_input_remove(data->gdktag);
47 close(data->fd);
48 kill(-data->subproc, SIGHUP);
49 data->gdktag = -1;
50 data->fd = -1;
51 data->subproc = 0;
52 conddisconn(conduit);
53 }
54 if(ret == 0)
55 {
56 gdk_input_remove(data->gdktag);
57 close(data->fd);
58 kill(-data->subproc, SIGHUP);
59 data->gdktag = -1;
60 data->fd = -1;
61 data->subproc = 0;
62 conddisconn(conduit);
63 }
64 data->inbufdata += ret;
65 while((p = memchr(data->inbuf, '\n', data->inbufdata)) != NULL)
66 {
67 *p = 0;
68 cmd = sstrdup(data->inbuf);
69 memmove(data->inbuf, p + 1, data->inbufdata -= (p - data->inbuf) + 1);
70 args = NULL;
71 argssize = argsdata = 0;
72 p = cmd;
73 do
74 {
75 if((p2 = strchr(p, '\t')) != NULL)
76 *(p2++) = 0;
77 addtobuf(args, p);
78 p = p2;
79 } while(p2 != NULL);
80 if(!strcmp(args[0], "N") && (argsdata >= 4))
81 {
82 transfer = newtransfer(conduit, args[1], atoi(args[2]), atoi(args[3]));
83 }
84 if(!strcmp(args[0], "D") && (argsdata >= 2))
85 {
86 if((transfer = findtransferbytag(conduit, args[1])) != NULL)
87 freetransfer(transfer);
88 }
89 if(!strcmp(args[0], "S") && (argsdata >= 3))
90 {
91 if((transfer = findtransferbytag(conduit, args[1])) != NULL)
92 transfersetsize(transfer, atoi(args[2]));
93 }
94 if(!strcmp(args[0], "P") && (argsdata >= 3))
95 {
96 if((transfer = findtransferbytag(conduit, args[1])) != NULL)
97 transfersetpos(transfer, atoi(args[2]));
98 }
99 free(args);
100 free(cmd);
101 }
102}
103
104static int init(struct conduit *conduit)
105{
106 static int inited = 0;
107 struct data *data;
108
109 if(!inited)
110 {
111 signal(SIGCHLD, SIG_IGN);
112 inited = 1;
113 }
114 data = smalloc(sizeof(*data));
115 memset(data, 0, sizeof(*data));
116 data->fd = -1;
117 data->inbuf = NULL;
118 data->inbufsize = data->inbufdata = 0;
119 data->gdktag = -1;
120 conduit->cdata = data;
121 return(0);
122}
123
124static int connect(struct conduit *conduit)
125{
126 struct data *data;
127 pid_t pid;
128 int pfd[2];
129
130 data = conduit->cdata;
131 if(pipe(pfd))
132 return(-1);
133 if((pid = fork()) < 0)
134 {
135 close(pfd[0]);
136 close(pfd[1]);
137 return(-1);
138 }
139 if(!pid)
140 {
141 int devnull;
142
143 setpgrp();
144 if((devnull = open("/dev/null", O_RDWR)) < 0)
145 exit(127);
146 close(pfd[0]);
147 dup2(pfd[1], 1);
148 close(pfd[1]);
149 dup2(devnull, 0);
150 close(devnull);
151 /* Leave stderr as is */
152 execl("/bin/sh", "sh", "-c", SUBPROCCMD, NULL);
153 exit(127);
154 }
155 close(pfd[1]);
156 fcntl(pfd[0], F_SETFL, fcntl(pfd[0], F_GETFL) | O_NONBLOCK);
157 data->subproc = pid;
158 data->fd = pfd[0];
159 data->gdktag = gdk_input_add(pfd[0], GDK_INPUT_READ, (void (*)(gpointer, gint, GdkInputCondition))pipefdcb, conduit);
160 data->inbufdata = 0;
161 return(0);
162}
163
164static void destroy(struct conduit *conduit)
165{
166 struct data *data;
167
168 data = conduit->cdata;
169 if(data == NULL)
170 return;
171 if(data->gdktag >= 0)
172 gdk_input_remove(data->gdktag);
173 if(data->subproc > 0)
174 kill(-data->subproc, SIGHUP);
175 if(data->fd >= 0)
176 close(data->fd);
177 if(data->inbuf != NULL)
178 free(data->inbuf);
179 free(data);
180 conduit->cdata = NULL;
181}
182
183static struct conduitiface st_conduit_pipe =
184{
185 .init = init,
186 .connect = connect,
187 .destroy = destroy,
188};
189
190struct conduitiface *conduit_pipe = &st_conduit_pipe;