Projet

Général

Profil

Télécharger (7,36 ko) Statistiques
| Branche: | Révision:

univnautes-tools / pfPorts / check_reload_status / files / fcgicli.c @ dbbbd083

1

    
2
#include <sys/types.h>
3
#include <sys/sbuf.h>
4
#include <sys/socket.h>
5
#include <sys/un.h>
6

    
7
#include <netinet/in.h>
8
#include <arpa/inet.h>
9

    
10
#include <err.h>
11
#include <errno.h>
12
#include <stdio.h>
13
#include <stdlib.h>
14
#include <string.h>
15
#include <strings.h>
16
#include <unistd.h>
17
#include <libgen.h>
18
#include <sys/utsname.h>
19
#include <time.h>
20

    
21
#include "fastcgi.h"
22
#include "common.h"
23

    
24
static int fcgisock = -1;
25
static struct sockaddr_un sun;
26
static struct sockaddr_in sin;
27
static int keepalive = 0;
28

    
29
static int
30
build_nvpair(struct sbuf *sb, const char *key, char *svalue)
31
{
32
	int lkey, lvalue;
33

    
34
	lkey = strlen(key);
35
	lvalue = strlen(svalue);
36

    
37
	if (lkey < 128)
38
		sbuf_putc(sb, lkey);
39
	else
40
		sbuf_printf(sb, "%c%c%c%c", (u_char)((lkey >> 24) | 0x80), (u_char)((lkey >> 16) & 0xFF), (u_char)((lkey >> 16) & 0xFF), (u_char)(lkey & 0xFF));
41

    
42
	if (lvalue < 128 || lvalue > 65535)
43
		sbuf_putc(sb, lvalue);
44
	else
45
		sbuf_printf(sb, "%c%c%c%c", (u_char)((lvalue >> 24) | 0x80), (u_char)((lvalue >> 16) & 0xFF), (u_char)((lvalue >> 16) & 0xFF), (u_char)(lvalue & 0xFF));
46

    
47
	if (lkey > 0)
48
		sbuf_printf(sb, "%s", key);
49
	if (lvalue > 0)
50
		sbuf_printf(sb, "%s", svalue);
51

    
52
	return (0);
53
}
54

    
55
static int
56
prepare_packet(FCGI_Header *header, int type, int lcontent, int requestId)
57
{
58
	header->version = (unsigned char)FCGI_VERSION_1;
59
	header->type = (unsigned char)type;
60
	header->requestIdB1 = (unsigned char)((requestId >> 8) & 0xFF);
61
	header->requestIdB0 = (unsigned char)(requestId & 0xFF);
62
	header->contentLengthB1 = (unsigned char)((lcontent >> 8) & 0xFF);
63
	header->contentLengthB0 = (unsigned char)(lcontent & 0xFF);
64

    
65
	return (0);
66
}
67

    
68
static char * 
69
read_packet(FCGI_Header *header, int sockfd)
70
{
71
	char *buf = NULL;
72
	int len, err;
73

    
74
	memset(header, 0, sizeof(*header));
75
	if (recv(sockfd, header, sizeof(*header), 0) > 0) {
76
		len = (header->requestIdB1 << 8) + header->requestIdB0;
77
		if (len != 1) {
78
			return (NULL);
79
		}
80
		len = (header->contentLengthB1 << 8) + header->contentLengthB0;
81
		len += header->paddingLength;
82
		//printf("LEN: %d, %d, %d: %s\n", len, header->type, (header->requestIdB1 << 8) + header->requestIdB0, (char *)header);
83
		if (len > 0) {
84
			buf = calloc(1, len);
85
			if (buf == NULL)
86
				return (NULL);
87

    
88
			err = recv(sockfd, buf, len, 0);
89
			if (err < 0) {
90
				free(buf);
91
				return (NULL);
92
			}
93
		}
94
	}
95

    
96
	return (buf);
97
}
98

    
99
static void
100
usage()
101
{
102
	printf("Usage: fcgicli [-d key=value] -f phpfiletocall -s phpfcgisocket -o [POST|GET]\n");
103
	exit(-10);
104
}
105

    
106
int
107
main(int argc, char **argv)
108
{
109
	FCGI_BeginRequestRecord *bHeader;
110
	FCGI_Header *tmpl, rHeader;
111
	struct sbuf *sbtmp2, *sbtmp;
112
	struct utsname uts;
113
	int ch, ispost = 0, len, result;
114
	char *data = NULL, *script = NULL, *socketpath, *mtype = NULL, *buf;
115

    
116
	tzset();
117

    
118
	socketpath = (char *)FCGI_SOCK_PATH;
119

    
120
	while ((ch = getopt(argc, argv, "d:f:ks:o:")) != -1) {
121
		switch (ch) {
122
		case 'd':
123
			data = optarg;
124
			break;
125
		case 'f':
126
			script = optarg;
127
			break;
128
		case 'k':
129
			keepalive = 1;
130
			break;
131
		case 's':
132
			socketpath = optarg;
133
			break;
134
		case 'o':
135
			if (!strcasecmp(optarg, "POST"))
136
				ispost = 1;
137
			else if(!strcasecmp(optarg, "GET"))
138
				ispost = 0;
139
			else
140
				usage();
141

    
142
			mtype = optarg;
143
			break;
144
		}
145
	}
146
	argc -= optind;
147
        argv += optind;
148

    
149
	if (socketpath == NULL) {
150
		printf("-s option is mandatory\n");
151
		usage();
152
	}
153
	if (script == NULL) {
154
		printf("-f option is mandatory\n");
155
		usage();
156
	}
157
	if (data != NULL && ispost) {
158
		printf("-d option is useful only with POST operation\n");
159
		usage();
160
	}
161

    
162
	if (strstr(socketpath, "/")) {
163
		fcgisock = socket(PF_UNIX, SOCK_STREAM, 0);
164
		if (fcgisock < 0)
165
			err(-2, "could not create socket.");
166

    
167
		bzero(&sun, sizeof(sun));
168
		sun.sun_family = AF_LOCAL;
169
		strlcpy(sun.sun_path, socketpath, sizeof(sun.sun_path));
170
		len = sizeof(sun);
171

    
172
		//alarm(3); /* Wait 3 seconds to complete a connect. More than enough?! */
173
		if (connect(fcgisock, (struct sockaddr *)&sun, len) < 0)
174
			errx(errno, "Could not connect to server(%s).", socketpath);
175
	} else {
176
		char *host, *port;
177
		if (!(port = strstr(socketpath, ":")))
178
			errx(-1, "Need the port specified as host:port");
179

    
180
		*port++ = '\0';
181
		host = socketpath;
182

    
183
		fcgisock = socket(PF_INET, SOCK_STREAM, 0);
184
		if (fcgisock < 0)
185
			err(-2, "could not create socket.");
186

    
187
		bzero(&sin, sizeof(sin));
188
		sin.sin_family = AF_INET;
189
		inet_pton(AF_INET, host, &sin.sin_addr); 
190
		sin.sin_port = htons(atoi(port));
191
		len = sizeof(sin);
192

    
193
		//alarm(3); /* Wait 3 seconds to complete a connect. More than enough?! */
194
		if (connect(fcgisock, (struct sockaddr *)&sin, len) < 0)
195
			errx(errno, "Could not connect to server(%s:%s).", host, port);
196
	}
197

    
198
	uname(&uts);
199

    
200
	if (ispost) {
201
		printf("POST is not yet implemented\n");
202
		tmpl = NULL;
203
		
204
	} else {
205
		sbtmp2 = sbuf_new_auto();
206
		if (sbtmp2 == NULL)
207
			errx(-3, "Could not allocate memory\n");
208
		build_nvpair(sbtmp2, "GATEWAY_INTERFACE", (char *)"FastCGI/1.0");
209
		build_nvpair(sbtmp2, "REQUEST_METHOD", (char *)"GET");
210
		build_nvpair(sbtmp2, "NO_HEADERS", (char *)"1");
211
		sbtmp = sbuf_new_auto();
212
		sbuf_printf(sbtmp, "/%s", basename(script));
213
		sbuf_finish(sbtmp);
214
		build_nvpair(sbtmp2, "SCRIPT_FILENAME", script);
215
		build_nvpair(sbtmp2, "SCRIPT_NAME", sbuf_data(sbtmp));
216
		if (data == NULL) {
217
			build_nvpair(sbtmp2, "REQUEST_URI", sbuf_data(sbtmp));
218
		}
219
		build_nvpair(sbtmp2, "DOCUMENT_URI", sbuf_data(sbtmp));
220
		sbuf_delete(sbtmp);
221
		if (data) {
222
			build_nvpair(sbtmp2, "QUERY_STRING", data); 
223
			sbtmp = sbuf_new_auto();
224
			sbuf_printf(sbtmp, "/%s?%s", basename(script), data);
225
			sbuf_finish(sbtmp);
226
			build_nvpair(sbtmp2, "REQUEST_URI", sbuf_data(sbtmp));
227
			sbuf_delete(sbtmp);
228
		}
229
		sbuf_finish(sbtmp2);
230

    
231
		len = (3 * sizeof(FCGI_Header)) + sizeof(FCGI_BeginRequestRecord) + sbuf_len(sbtmp2);
232
		buf = calloc(1, len);
233
		if (buf == NULL)
234
			errx(-4, "Cannot allocate memory");
235

    
236
		bHeader = (FCGI_BeginRequestRecord *)buf;
237
		prepare_packet(&bHeader->header, FCGI_BEGIN_REQUEST, sizeof(bHeader->body), 1);
238
		bHeader->body.roleB0 = (unsigned char)FCGI_RESPONDER;
239
		bHeader->body.flags = (unsigned char)(keepalive ? FCGI_KEEP_CONN : 0);
240
		bHeader++;
241
		tmpl = (FCGI_Header *)bHeader;
242
		prepare_packet(tmpl, FCGI_PARAMS, sbuf_len(sbtmp2), 1);
243
		tmpl++;
244
		memcpy((char *)tmpl, sbuf_data(sbtmp2), sbuf_len(sbtmp2));
245
		tmpl = (FCGI_Header *)(((char *)tmpl) + sbuf_len(sbtmp2));
246
		sbuf_delete(sbtmp2);
247
	}
248
	prepare_packet(tmpl, FCGI_PARAMS, 0, 1);
249
	tmpl++;
250
	prepare_packet(tmpl, FCGI_STDIN, 0, 1);
251
	while (len > 0) {
252
		result = write(fcgisock, buf, len);
253
		if (result < 0) {
254
			printf("Something wrong happened while sending request\n");
255
			free(buf);
256
			close(fcgisock);
257
			exit(-2);
258
		}
259
		len -= result;
260
		buf += result;
261
	}
262
	free(buf);
263

    
264
	do {
265
		buf = read_packet(&rHeader, fcgisock);
266
		if (buf == NULL) {
267
			printf("Something wrong happened while reading request\n");
268
			close(fcgisock);
269
			exit(-1);
270
		}
271
		switch (rHeader.type) {
272
		case FCGI_DATA:
273
		case FCGI_STDOUT:
274
		case FCGI_STDERR:
275
			printf("%s", buf);
276
			free(buf);
277
			break;
278
		case FCGI_ABORT_REQUEST:
279
			printf("Request aborted\n");
280
			free(buf);
281
			goto endprog;
282
			break;
283
		case FCGI_END_REQUEST:
284
			switch (((FCGI_EndRequestBody *)buf)->protocolStatus) {
285
			case FCGI_CANT_MPX_CONN:
286
				printf("The FCGI server cannot multiplex\n");
287
				break;
288
			case FCGI_OVERLOADED:
289
				printf("The FCGI server is overloaded\n");
290
				break;
291
			case FCGI_UNKNOWN_ROLE:
292
				printf("FCGI role is unknown\n");
293
				break;
294
			case FCGI_REQUEST_COMPLETE:
295
				break;
296
			}
297
			free(buf);
298
			goto endprog;
299
			break;
300
		}
301
	} while (rHeader.type != FCGI_END_REQUEST);
302

    
303
endprog:
304
	close(fcgisock);
305

    
306
	return (0);
307
}
(4-4/6)