Projet

Général

Profil

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

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

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
				printf("POST mode is not yet implemented\n");
138
				exit(-2);
139
			} else if(!strcasecmp(optarg, "GET"))
140
				ispost = 0;
141
			else
142
				usage();
143

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

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

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

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

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

    
182
		*port++ = '\0';
183
		host = socketpath;
184

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

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

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

    
200
	uname(&uts);
201

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

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

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

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

    
299
endprog:
300
	close(fcgisock);
301

    
302
	return (0);
303
}
(4-4/6)