ruby-fcgi 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.8.8
data/ext/fcgi/MANIFEST ADDED
@@ -0,0 +1,3 @@
1
+ MANIFEST
2
+ extconf.rb
3
+ fcgi.c
data/ext/fcgi/Makefile ADDED
@@ -0,0 +1,181 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = /tmp/ruby-fcgi-0.8.7/ext/fcgi
7
+ topdir = /usr/include/ruby-1.9.1
8
+ hdrdir = /usr/include/ruby-1.9.1
9
+ arch_hdrdir = /usr/include/ruby-1.9.1/$(arch)
10
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
11
+ prefix = $(DESTDIR)/usr
12
+ exec_prefix = $(prefix)
13
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
14
+ sitehdrdir = $(rubyhdrdir)/site_ruby
15
+ rubyhdrdir = $(includedir)/ruby-$(ruby_version)
16
+ vendordir = $(DESTDIR)/usr/lib/ruby/vendor_ruby
17
+ sitedir = $(DESTDIR)/usr/local/lib/site_ruby
18
+ mandir = $(prefix)/share/man
19
+ localedir = $(datarootdir)/locale
20
+ libdir = $(exec_prefix)/lib
21
+ psdir = $(docdir)
22
+ pdfdir = $(docdir)
23
+ dvidir = $(docdir)
24
+ htmldir = $(docdir)
25
+ infodir = $(prefix)/share/info
26
+ docdir = $(datarootdir)/doc/$(PACKAGE)
27
+ oldincludedir = $(DESTDIR)/usr/include
28
+ includedir = $(prefix)/include
29
+ localstatedir = $(DESTDIR)/var
30
+ sharedstatedir = $(prefix)/com
31
+ sysconfdir = $(DESTDIR)/etc
32
+ datadir = $(datarootdir)
33
+ datarootdir = $(prefix)/share
34
+ libexecdir = $(prefix)/lib/ruby1.9.1
35
+ sbindir = $(exec_prefix)/sbin
36
+ bindir = $(exec_prefix)/bin
37
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
38
+ archdir = $(rubylibdir)/$(arch)
39
+ sitelibdir = $(sitedir)/$(ruby_version)
40
+ sitearchdir = $(sitelibdir)/$(sitearch)
41
+ vendorlibdir = $(vendordir)/$(ruby_version)
42
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
43
+
44
+ CC = cc
45
+ CXX = g++
46
+ LIBRUBY = $(LIBRUBY_SO)
47
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
48
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
49
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
50
+ OUTFLAG = -o
51
+ COUTFLAG = -o
52
+
53
+ RUBY_EXTCONF_H =
54
+ cflags = $(optflags) $(debugflags) $(warnflags)
55
+ optflags = -O2
56
+ debugflags = -g
57
+ warnflags = -Wall -Wno-parentheses
58
+ CFLAGS = -fPIC -fno-strict-aliasing -g -g -O2 $(cflags) -fPIC
59
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
60
+ DEFS = -D_FILE_OFFSET_BITS=64
61
+ CPPFLAGS = -DHAVE_FCGIAPP_H $(DEFS) $(cppflags)
62
+ CXXFLAGS = $(CFLAGS) -fno-strict-aliasing -g $(cxxflags)
63
+ ldflags = -L. -Wl,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic
64
+ dldflags =
65
+ archflag =
66
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
67
+ LDSHARED = $(CC) -shared
68
+ LDSHAREDXX = $(CXX) -shared
69
+ AR = ar
70
+ EXEEXT =
71
+
72
+ RUBY_INSTALL_NAME = ruby1.9.1
73
+ RUBY_SO_NAME = ruby-1.9.1
74
+ arch = i486-linux
75
+ sitearch = i486-linux
76
+ ruby_version = 1.9.1
77
+ ruby = /usr/bin/ruby1.9.1
78
+ RUBY = $(ruby)
79
+ RM = rm -f
80
+ RM_RF = $(RUBY) -run -e rm -- -rf
81
+ RMDIRS = $(RUBY) -run -e rmdir -- -p
82
+ MAKEDIRS = mkdir -p
83
+ INSTALL = /usr/bin/install -c
84
+ INSTALL_PROG = $(INSTALL) -m 0755
85
+ INSTALL_DATA = $(INSTALL) -m 644
86
+ COPY = cp
87
+
88
+ #### End of system configuration section. ####
89
+
90
+ preload =
91
+
92
+ libpath = . $(libdir)
93
+ LIBPATH = -L. -L$(libdir)
94
+ DEFFILE =
95
+
96
+ CLEANFILES = mkmf.log
97
+ DISTCLEANFILES =
98
+ DISTCLEANDIRS =
99
+
100
+ extout =
101
+ extout_prefix =
102
+ target_prefix =
103
+ LOCAL_LIBS =
104
+ LIBS = $(LIBRUBYARG_SHARED) -lfcgi -lpthread -lrt -ldl -lcrypt -lm -lc
105
+ SRCS = fcgi.c
106
+ OBJS = fcgi.o
107
+ TARGET = fcgi
108
+ DLLIB = $(TARGET).so
109
+ EXTSTATIC =
110
+ STATIC_LIB =
111
+
112
+ BINDIR = $(bindir)
113
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
114
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
115
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
116
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
117
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
118
+
119
+ TARGET_SO = $(DLLIB)
120
+ CLEANLIBS = $(TARGET).so
121
+ CLEANOBJS = *.o *.bak
122
+
123
+ all: $(DLLIB)
124
+ static: $(STATIC_LIB)
125
+
126
+ clean-rb-default::
127
+ clean-rb::
128
+ clean-so::
129
+ clean: clean-so clean-rb-default clean-rb
130
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
131
+
132
+ distclean-rb-default::
133
+ distclean-rb::
134
+ distclean-so::
135
+ distclean: clean distclean-so distclean-rb-default distclean-rb
136
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
137
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
138
+ @-$(RMDIRS) $(DISTCLEANDIRS)
139
+
140
+ realclean: distclean
141
+ install: install-so install-rb
142
+
143
+ install-so: $(RUBYARCHDIR)
144
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
145
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
146
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
147
+ install-rb: pre-install-rb install-rb-default
148
+ install-rb-default: pre-install-rb-default
149
+ pre-install-rb: Makefile
150
+ pre-install-rb-default: Makefile
151
+ $(RUBYARCHDIR):
152
+ $(MAKEDIRS) $@
153
+
154
+ site-install: site-install-so site-install-rb
155
+ site-install-so: install-so
156
+ site-install-rb: install-rb
157
+
158
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
159
+
160
+ .cc.o:
161
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
162
+
163
+ .cxx.o:
164
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
165
+
166
+ .cpp.o:
167
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
168
+
169
+ .C.o:
170
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
171
+
172
+ .c.o:
173
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
174
+
175
+ $(DLLIB): $(OBJS) Makefile
176
+ @-$(RM) $(@)
177
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
178
+
179
+
180
+
181
+ $(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
@@ -0,0 +1,7 @@
1
+ require "mkmf"
2
+
3
+ dir_config("fcgi")
4
+
5
+ if (have_header("fcgiapp.h") || have_header("fastcgi/fcgiapp.h")) && have_library("fcgi", "FCGX_Accept")
6
+ create_makefile("fcgi")
7
+ end
data/ext/fcgi/fcgi.c ADDED
@@ -0,0 +1,558 @@
1
+ /*
2
+ * fcgi.c
3
+ * Copyright (C) 1998-1999 Network Applied Communication Laboratory, Inc.
4
+ * Copyright (C) 2002-2006 MoonWolf <moonwolf@moonwolf.com>
5
+ */
6
+
7
+ #include <stdio.h>
8
+ #include <sys/types.h>
9
+ #include <unistd.h>
10
+ #include <errno.h>
11
+ #include <fcntl.h>
12
+
13
+ #include "ruby.h"
14
+ #ifdef HAVE_FASTCGI_FCGIAPP_H
15
+ #include <fastcgi/fcgiapp.h>
16
+ #else
17
+ #include "fcgiapp.h"
18
+ #endif
19
+
20
+ static VALUE cFCGI;
21
+ static VALUE eFCGIError;
22
+ static VALUE cFCGIStream;
23
+ static VALUE eFCGIStreamError;
24
+ static VALUE eFCGIStreamUnsupportedVersionError;
25
+ static VALUE eFCGIStreamProtocolError;
26
+ static VALUE eFCGIStreamParamsError;
27
+ static VALUE eFCGIStreamCallSeqError;
28
+
29
+ typedef struct fcgi_data {
30
+ FCGX_Request *req;
31
+ VALUE in;
32
+ VALUE out;
33
+ VALUE err;
34
+ VALUE env;
35
+ } fcgi_data;
36
+
37
+ static void fcgi_mark(fcgi_data *data)
38
+ {
39
+ /* rb_gc_mark(data->req); */
40
+ rb_gc_mark(data->in);
41
+ rb_gc_mark(data->out);
42
+ rb_gc_mark(data->err);
43
+ rb_gc_mark(data->env);
44
+ }
45
+
46
+ static void fcgi_free_req(fcgi_data *data)
47
+ {
48
+ free(data->req);
49
+ free(data);
50
+ }
51
+
52
+ static VALUE fcgi_s_accept(VALUE self)
53
+ {
54
+ int status;
55
+ FCGX_Request *req;
56
+ fd_set readfds;
57
+
58
+ req = ALLOC(FCGX_Request);
59
+
60
+ status = FCGX_InitRequest(req,0,0);
61
+ if (status != 0) {
62
+ rb_raise(eFCGIError, "FCGX_Init() failed");
63
+ return Qnil;
64
+ }
65
+
66
+ FD_ZERO(&readfds);
67
+ FD_SET(req->listen_sock, &readfds);
68
+ if (rb_thread_select(req->listen_sock+1, &readfds, NULL, NULL, NULL) < 1) {
69
+ return Qnil;
70
+ }
71
+
72
+ status = FCGX_Accept_r(req);
73
+ if (status >= 0) {
74
+ fcgi_data *data;
75
+ char **env;
76
+ VALUE obj,key, value;
77
+ char *pkey,*pvalue;
78
+ int flags, fd;
79
+
80
+ /* Unset NONBLOCKING */
81
+ fd = ((FCGX_Request*) req)->ipcFd;
82
+ flags = fcntl(fd, F_GETFL);
83
+
84
+ if (flags & O_NONBLOCK) {
85
+ fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
86
+ }
87
+
88
+ obj = Data_Make_Struct(self, fcgi_data, fcgi_mark, fcgi_free_req, data);
89
+ data->req = req;
90
+ data->in = Data_Wrap_Struct(cFCGIStream, 0, 0, req->in);
91
+ data->out = Data_Wrap_Struct(cFCGIStream, 0, 0, req->out);
92
+ data->err = Data_Wrap_Struct(cFCGIStream, 0, 0, req->err);
93
+ data->env = rb_hash_new();
94
+ env = req->envp;
95
+ for (; *env; env++) {
96
+ int size = 0;
97
+ pkey = *env;
98
+ pvalue = pkey;
99
+ while( *(pvalue++) != '=') size++;
100
+ key = rb_str_new(pkey, size);
101
+ value = rb_str_new2(pvalue);
102
+ OBJ_TAINT(key);
103
+ OBJ_TAINT(value);
104
+ rb_hash_aset(data->env, key, value);
105
+ }
106
+
107
+ return obj;
108
+ } else {
109
+ return Qnil;
110
+ }
111
+ }
112
+
113
+ static VALUE fcgi_s_each(VALUE self)
114
+ {
115
+ VALUE fcgi;
116
+
117
+ while ((fcgi = fcgi_s_accept(self)) != Qnil) {
118
+ rb_yield(fcgi);
119
+ }
120
+ return Qnil;
121
+ }
122
+
123
+ static VALUE fcgi_s_iscgi(VALUE self)
124
+ {
125
+ if (FCGX_IsCGI()) {
126
+ return Qtrue;
127
+ } else {
128
+ return Qfalse;
129
+ }
130
+ }
131
+
132
+ static VALUE fcgi_in(VALUE self)
133
+ {
134
+ fcgi_data *data;
135
+
136
+ Data_Get_Struct(self, fcgi_data, data);
137
+ return data->in;
138
+ }
139
+
140
+ static VALUE fcgi_out(VALUE self)
141
+ {
142
+ fcgi_data *data;
143
+
144
+ Data_Get_Struct(self, fcgi_data, data);
145
+ return data->out;
146
+ }
147
+
148
+ static VALUE fcgi_err(VALUE self)
149
+ {
150
+ fcgi_data *data;
151
+
152
+ Data_Get_Struct(self, fcgi_data, data);
153
+ return data->err;
154
+ }
155
+
156
+ static VALUE fcgi_env(VALUE self)
157
+ {
158
+ fcgi_data *data;
159
+
160
+ Data_Get_Struct(self, fcgi_data, data);
161
+ return data->env;
162
+ }
163
+
164
+ static VALUE fcgi_finish(VALUE self)
165
+ {
166
+ fcgi_data *data;
167
+
168
+ Data_Get_Struct(self, fcgi_data, data);
169
+
170
+ FCGX_Finish_r(data->req);
171
+
172
+ return Qtrue;
173
+ }
174
+
175
+ #define CHECK_STREAM_ERROR(stream) {\
176
+ int err = FCGX_GetError(stream);\
177
+ extern int errno; \
178
+ if (err) {\
179
+ if (err > 0) {\
180
+ errno = err;\
181
+ rb_sys_fail(NULL);\
182
+ }\
183
+ else {\
184
+ switch (err) {\
185
+ case FCGX_UNSUPPORTED_VERSION:\
186
+ rb_raise(eFCGIStreamUnsupportedVersionError, "unsupported version");\
187
+ break;\
188
+ case FCGX_PROTOCOL_ERROR:\
189
+ rb_raise(eFCGIStreamProtocolError, "protocol error");\
190
+ break;\
191
+ case FCGX_PARAMS_ERROR:\
192
+ rb_raise(eFCGIStreamProtocolError, "parameter error");\
193
+ break;\
194
+ case FCGX_CALL_SEQ_ERROR:\
195
+ rb_raise(eFCGIStreamCallSeqError, "preconditions are not met");\
196
+ break;\
197
+ default:\
198
+ rb_raise(eFCGIStreamError, "unknown error");\
199
+ break;\
200
+ }\
201
+ }\
202
+ }\
203
+ }
204
+
205
+ static VALUE fcgi_stream_putc(VALUE self, VALUE ch)
206
+ {
207
+ FCGX_Stream *stream;
208
+ int c;
209
+
210
+ rb_secure(4);
211
+ Data_Get_Struct(self, FCGX_Stream, stream);
212
+ if ((c = FCGX_PutChar(NUM2INT(ch), stream)) == EOF)
213
+ CHECK_STREAM_ERROR(stream);
214
+ return INT2NUM(c);
215
+ }
216
+
217
+ static VALUE fcgi_stream_write(VALUE self, VALUE str)
218
+ {
219
+ FCGX_Stream *stream;
220
+ int len;
221
+
222
+ rb_secure(4);
223
+ Data_Get_Struct(self, FCGX_Stream, stream);
224
+ str = rb_obj_as_string(str);
225
+ len = FCGX_PutStr(RSTRING_PTR(str), RSTRING_LEN(str), stream);
226
+ if (len == EOF) CHECK_STREAM_ERROR(stream);
227
+ return INT2NUM(len);
228
+ }
229
+
230
+ static VALUE fcgi_stream_print(int argc, VALUE *argv, VALUE out)
231
+ {
232
+ int i;
233
+ VALUE line;
234
+
235
+ /* if no argument given, print `$_' */
236
+ if (argc == 0) {
237
+ argc = 1;
238
+ line = rb_lastline_get();
239
+ argv = &line;
240
+ }
241
+ for (i=0; i<argc; i++) {
242
+ if (!NIL_P(rb_output_fs) && i>0) {
243
+ fcgi_stream_write(out, rb_output_fs);
244
+ }
245
+ switch (TYPE(argv[i])) {
246
+ case T_NIL:
247
+ fcgi_stream_write(out, rb_str_new2("nil"));
248
+ break;
249
+ default:
250
+ fcgi_stream_write(out, argv[i]);
251
+ break;
252
+ }
253
+ }
254
+ if (!NIL_P(rb_output_rs)) {
255
+ fcgi_stream_write(out, rb_output_rs);
256
+ }
257
+
258
+ return Qnil;
259
+ }
260
+
261
+ static VALUE fcgi_stream_printf(int argc, VALUE *argv, VALUE out)
262
+ {
263
+ fcgi_stream_write(out, rb_f_sprintf(argc, argv));
264
+ return Qnil;
265
+ }
266
+
267
+ static VALUE fcgi_stream_puts _((int, VALUE*, VALUE));
268
+
269
+ static VALUE fcgi_stream_puts_ary(VALUE ary, VALUE out)
270
+ {
271
+ VALUE tmp;
272
+ int i;
273
+
274
+ for (i=0; i<RARRAY_LEN(ary); i++) {
275
+ tmp = RARRAY_PTR(ary)[i];
276
+ if (rb_inspecting_p(tmp)) {
277
+ tmp = rb_str_new2("[...]");
278
+ }
279
+ fcgi_stream_puts(1, &tmp, out);
280
+ }
281
+ return Qnil;
282
+ }
283
+
284
+ static VALUE fcgi_stream_puts(int argc, VALUE *argv, VALUE out)
285
+ {
286
+ int i;
287
+ VALUE line;
288
+
289
+ /* if no argument given, print newline. */
290
+ if (argc == 0) {
291
+ fcgi_stream_write(out, rb_default_rs);
292
+ return Qnil;
293
+ }
294
+ for (i=0; i<argc; i++) {
295
+ switch (TYPE(argv[i])) {
296
+ case T_NIL:
297
+ line = rb_str_new2("nil");
298
+ break;
299
+ case T_ARRAY:
300
+ rb_protect_inspect(fcgi_stream_puts_ary, argv[i], out);
301
+ continue;
302
+ default:
303
+ line = argv[i];
304
+ break;
305
+ }
306
+ line = rb_obj_as_string(line);
307
+ fcgi_stream_write(out, line);
308
+ if (RSTRING_PTR(line)[RSTRING_LEN(line)-1] != '\n') {
309
+ fcgi_stream_write(out, rb_default_rs);
310
+ }
311
+ }
312
+
313
+ return Qnil;
314
+ }
315
+
316
+ static VALUE fcgi_stream_addstr(VALUE out, VALUE str)
317
+ {
318
+ fcgi_stream_write(out, str);
319
+ return out;
320
+ }
321
+
322
+ static VALUE fcgi_stream_flush(VALUE self)
323
+ {
324
+ FCGX_Stream *stream;
325
+
326
+ Data_Get_Struct(self, FCGX_Stream, stream);
327
+ if (FCGX_FFlush(stream) == EOF)
328
+ CHECK_STREAM_ERROR(stream);
329
+ return Qnil;
330
+ }
331
+
332
+ static VALUE fcgi_stream_getc(VALUE self)
333
+ {
334
+ FCGX_Stream *stream;
335
+ int c;
336
+
337
+ Data_Get_Struct(self, FCGX_Stream, stream);
338
+ if ((c = FCGX_GetChar(stream)) == EOF) {
339
+ CHECK_STREAM_ERROR(stream);
340
+ return Qnil;
341
+ }
342
+ else {
343
+ return INT2NUM(c);
344
+ }
345
+ }
346
+
347
+ static VALUE fcgi_stream_ungetc(VALUE self, VALUE ch)
348
+ {
349
+ FCGX_Stream *stream;
350
+ int c;
351
+
352
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
353
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
354
+ }
355
+ Data_Get_Struct(self, FCGX_Stream, stream);
356
+ c = FCGX_UnGetChar(NUM2INT(ch), stream);
357
+ CHECK_STREAM_ERROR(stream);
358
+ return INT2NUM(c);
359
+ }
360
+
361
+ static VALUE fcgi_stream_gets(VALUE self)
362
+ {
363
+ FCGX_Stream *stream;
364
+ char buff[BUFSIZ];
365
+ VALUE str = rb_str_new("", 0);
366
+ OBJ_TAINT(str);
367
+
368
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
369
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
370
+ }
371
+
372
+ Data_Get_Struct(self, FCGX_Stream, stream);
373
+
374
+ for (;;) {
375
+ if (FCGX_GetLine(buff, BUFSIZ, stream) == NULL) {
376
+ CHECK_STREAM_ERROR(stream);
377
+ break;
378
+ }
379
+ rb_str_cat(str, buff, strlen(buff));
380
+ if (strchr(buff, '\n')) break;
381
+ }
382
+ if (RSTRING_LEN(str) > 0)
383
+ return str;
384
+ else
385
+ return Qnil;
386
+ }
387
+
388
+ static VALUE fcgi_stream_read(int argc, VALUE *argv, VALUE self)
389
+ {
390
+ VALUE num,str;
391
+ FCGX_Stream *stream;
392
+ char *buff;
393
+ int n;
394
+
395
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
396
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
397
+ }
398
+
399
+ Data_Get_Struct(self, FCGX_Stream, stream);
400
+
401
+ if (argc==0) {
402
+ buff = ALLOC_N(char, 16384);
403
+ n = FCGX_GetStr(buff, 16384, stream);
404
+ CHECK_STREAM_ERROR(stream);
405
+ if (n == 0) {
406
+ free(buff);
407
+ return Qnil;
408
+ }
409
+ str = rb_str_new(buff, n);
410
+ OBJ_TAINT(str);
411
+
412
+ while(!FCGX_HasSeenEOF(stream)) {
413
+ n = FCGX_GetStr(buff, 16384, stream);
414
+ CHECK_STREAM_ERROR(stream);
415
+ if (n > 0) {
416
+ rb_str_cat(str, buff, n);
417
+ } else {
418
+ free(buff);
419
+ return Qnil;
420
+ }
421
+ }
422
+ free(buff);
423
+ return str;
424
+ }
425
+
426
+ num = argv[0];
427
+ n = NUM2INT(num);
428
+
429
+ buff = ALLOC_N(char, n);
430
+ n = FCGX_GetStr(buff, n, stream);
431
+ CHECK_STREAM_ERROR(stream);
432
+ if (n > 0) {
433
+ str = rb_str_new(buff, n);
434
+ OBJ_TAINT(str);
435
+ free(buff);
436
+ return str;
437
+ }
438
+ else {
439
+ free(buff);
440
+ return Qnil;
441
+ }
442
+ }
443
+
444
+ static VALUE fcgi_stream_eof(VALUE self)
445
+ {
446
+ FCGX_Stream *stream;
447
+
448
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
449
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
450
+ }
451
+ Data_Get_Struct(self, FCGX_Stream, stream);
452
+ return FCGX_HasSeenEOF(stream) ? Qtrue : Qfalse;
453
+ }
454
+
455
+ static VALUE fcgi_stream_close(VALUE self)
456
+ {
457
+ FCGX_Stream *stream;
458
+
459
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
460
+ rb_raise(rb_eSecurityError, "Insecure: can't close");
461
+ }
462
+ Data_Get_Struct(self, FCGX_Stream, stream);
463
+ if (FCGX_FClose(stream) == EOF)
464
+ CHECK_STREAM_ERROR(stream);
465
+ return Qnil;
466
+ }
467
+
468
+ static VALUE fcgi_stream_closed(VALUE self)
469
+ {
470
+ FCGX_Stream *stream;
471
+
472
+ Data_Get_Struct(self, FCGX_Stream, stream);
473
+ return stream->isClosed ? Qtrue : Qfalse;
474
+ }
475
+
476
+ static VALUE fcgi_stream_binmode(VALUE self)
477
+ {
478
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
479
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
480
+ }
481
+ return self;
482
+ }
483
+
484
+ static VALUE fcgi_stream_isatty(VALUE self)
485
+ {
486
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
487
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
488
+ }
489
+ return Qfalse;
490
+ }
491
+
492
+ static VALUE fcgi_stream_sync(VALUE self)
493
+ {
494
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
495
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
496
+ }
497
+ return Qfalse;
498
+ }
499
+
500
+ static VALUE fcgi_stream_setsync(VALUE self,VALUE sync)
501
+ {
502
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
503
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
504
+ }
505
+ return Qfalse;
506
+ }
507
+
508
+
509
+
510
+ void Init_fcgi() {
511
+
512
+ FCGX_Init();
513
+
514
+ cFCGI = rb_define_class("FCGI", rb_cObject);
515
+ eFCGIError =rb_define_class_under(cFCGI, "Error", rb_eStandardError);
516
+ rb_define_singleton_method(cFCGI, "accept", fcgi_s_accept, 0);
517
+ rb_define_singleton_method(cFCGI, "each", fcgi_s_each, 0);
518
+ rb_define_singleton_method(cFCGI, "each_request", fcgi_s_each, 0);
519
+ rb_define_singleton_method(cFCGI, "is_cgi?", fcgi_s_iscgi, 0);
520
+ rb_define_method(cFCGI, "in", fcgi_in, 0);
521
+ rb_define_method(cFCGI, "out", fcgi_out, 0);
522
+ rb_define_method(cFCGI, "err", fcgi_err, 0);
523
+ rb_define_method(cFCGI, "env", fcgi_env, 0);
524
+ rb_define_method(cFCGI, "finish", fcgi_finish, 0);
525
+
526
+ cFCGIStream = rb_define_class_under(cFCGI, "Stream", rb_cObject);
527
+ eFCGIStreamError =rb_define_class_under(cFCGIStream, "Error", rb_eStandardError);
528
+ eFCGIStreamUnsupportedVersionError =
529
+ rb_define_class_under(cFCGIStream, "UnsupportedVersionError",
530
+ eFCGIStreamError);
531
+ eFCGIStreamProtocolError = rb_define_class_under(cFCGIStream, "ProtocolError",
532
+ eFCGIStreamError);
533
+ eFCGIStreamParamsError = rb_define_class_under(cFCGIStream, "ParamsError",
534
+ eFCGIStreamError);
535
+ eFCGIStreamCallSeqError = rb_define_class_under(cFCGIStream, "CallSeqError",
536
+ eFCGIStreamError);
537
+ rb_undef_method(CLASS_OF(cFCGIStream), "new");
538
+ rb_define_method(cFCGIStream, "putc", fcgi_stream_putc, 1);
539
+ rb_define_method(cFCGIStream, "write", fcgi_stream_write, 1);
540
+ rb_define_method(cFCGIStream, "print", fcgi_stream_print, -1);
541
+ rb_define_method(cFCGIStream, "printf", fcgi_stream_printf, -1);
542
+ rb_define_method(cFCGIStream, "puts", fcgi_stream_puts, -1);
543
+ rb_define_method(cFCGIStream, "<<", fcgi_stream_addstr, 1);
544
+ rb_define_method(cFCGIStream, "flush", fcgi_stream_flush, 0);
545
+ rb_define_method(cFCGIStream, "getc", fcgi_stream_getc, 0);
546
+ rb_define_method(cFCGIStream, "ungetc", fcgi_stream_ungetc, 1);
547
+ rb_define_method(cFCGIStream, "gets", fcgi_stream_gets, 0);
548
+ rb_define_method(cFCGIStream, "read", fcgi_stream_read, -1);
549
+ rb_define_method(cFCGIStream, "eof", fcgi_stream_eof, 0);
550
+ rb_define_method(cFCGIStream, "eof?", fcgi_stream_eof, 0);
551
+ rb_define_method(cFCGIStream, "close", fcgi_stream_close, 0);
552
+ rb_define_method(cFCGIStream, "closed?", fcgi_stream_closed, 0);
553
+ rb_define_method(cFCGIStream, "binmode", fcgi_stream_binmode, 0);
554
+ rb_define_method(cFCGIStream, "isatty", fcgi_stream_isatty, 0);
555
+ rb_define_method(cFCGIStream, "tty?", fcgi_stream_isatty, 0);
556
+ rb_define_method(cFCGIStream, "sync", fcgi_stream_sync, 0);
557
+ rb_define_method(cFCGIStream, "sync=", fcgi_stream_setsync, 1);
558
+ }