ruby-lsapi 1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,296 @@
1
+ /*
2
+ Copyright (c) 2005, Lite Speed Technologies Inc.
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are
7
+ met:
8
+
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above
12
+ copyright notice, this list of conditions and the following
13
+ disclaimer in the documentation and/or other materials provided
14
+ with the distribution.
15
+ * Neither the name of the Lite Speed Technologies Inc nor the
16
+ names of its contributors may be used to endorse or promote
17
+ products derived from this software without specific prior
18
+ written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+ /***************************************************************************
34
+ lsapilib.h - description
35
+ -------------------
36
+ begin : Mon Feb 21 2005
37
+ copyright : (C) 2005 by George Wang
38
+ email : gwang@litespeedtech.com
39
+ ***************************************************************************/
40
+
41
+
42
+ #ifndef _LSAPILIB_H_
43
+ #define _LSAPILIB_H_
44
+
45
+ #if defined (c_plusplus) || defined (__cplusplus)
46
+ extern "C" {
47
+ #endif
48
+
49
+ #include <stddef.h>
50
+ #include <lsapidef.h>
51
+
52
+ struct LSAPI_key_value_pair
53
+ {
54
+ char * pKey;
55
+ char * pValue;
56
+ int keyLen;
57
+ int valLen;
58
+ };
59
+
60
+
61
+ #define LSAPI_MAX_RESP_HEADERS 100
62
+
63
+ typedef struct lsapi_request
64
+ {
65
+ int m_fdListen;
66
+ int m_fd;
67
+
68
+ char * m_pReqBuf;
69
+ int m_reqBufSize;
70
+
71
+ char * m_pRespBuf;
72
+ char * m_pRespBufEnd;
73
+ char * m_pRespBufPos;
74
+
75
+ char * m_pRespHeaderBuf;
76
+ char * m_pRespHeaderBufEnd;
77
+ char * m_pRespHeaderBufPos;
78
+
79
+
80
+ struct iovec * m_pIovec;
81
+ struct iovec * m_pIovecEnd;
82
+ struct iovec * m_pIovecCur;
83
+ struct iovec * m_pIovecToWrite;
84
+
85
+ struct lsapi_packet_header * m_respPktHeaderEnd;
86
+
87
+ struct lsapi_req_header * m_pHeader;
88
+ struct LSAPI_key_value_pair * m_pEnvList;
89
+ struct LSAPI_key_value_pair * m_pSpecialEnvList;
90
+ int m_envListSize;
91
+ int m_specialEnvListSize;
92
+
93
+ struct lsapi_http_header_index * m_pHeaderIndex;
94
+ struct lsapi_header_offset * m_pUnknownHeader;
95
+
96
+ char * m_pScriptFile;
97
+ char * m_pScriptName;
98
+ char * m_pQueryString;
99
+ char * m_pHttpHeader;
100
+ char * m_pRequestMethod;
101
+ int m_totalLen;
102
+ int m_reqState;
103
+ int m_reqBodyRead;
104
+ int m_bufProcessed;
105
+ int m_bufRead;
106
+
107
+ struct lsapi_packet_header m_respPktHeader[5];
108
+
109
+ struct lsapi_resp_header m_respHeader;
110
+ short m_respHeaderLen[LSAPI_MAX_RESP_HEADERS];
111
+
112
+ }LSAPI_Request;
113
+
114
+ extern LSAPI_Request g_req;
115
+
116
+
117
+ //return: >0 continue, ==0 stop, -1 failed
118
+ typedef int (*LSAPI_CB_EnvHandler )( const char * pKey, int keyLen,
119
+ const char * pValue, int valLen, void * arg );
120
+
121
+
122
+ int LSAPI_Init(void);
123
+
124
+ void LSAPI_stop(void);
125
+
126
+ int LSAPI_Is_Listen_r( LSAPI_Request * pReq);
127
+
128
+ int LSAPI_InitRequest( LSAPI_Request * pReq, int fd );
129
+
130
+ int LSAPI_Accept_r( LSAPI_Request * pReq );
131
+
132
+ void LSAPI_Reset_r( LSAPI_Request * pReq );
133
+
134
+ int LSAPI_Finish_r( LSAPI_Request * pReq );
135
+
136
+ int LSAPI_Release_r( LSAPI_Request * pReq );
137
+
138
+ char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex );
139
+
140
+ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
141
+ LSAPI_CB_EnvHandler fn, void * arg );
142
+
143
+ int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
144
+ LSAPI_CB_EnvHandler fn, void * arg );
145
+
146
+ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
147
+ LSAPI_CB_EnvHandler fn, void * arg );
148
+
149
+ char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name );
150
+
151
+
152
+ int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int len );
153
+
154
+
155
+ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq );
156
+
157
+ int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len );
158
+
159
+ int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len );
160
+
161
+ int LSAPI_Flush_r( LSAPI_Request * pReq );
162
+
163
+ int LSAPI_AppendRespHeader_r( LSAPI_Request * pHeader, char * pBuf, int len );
164
+
165
+ static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code )
166
+ {
167
+ if ( !pReq )
168
+ return -1;
169
+ pReq->m_respHeader.m_respInfo.m_status = code;
170
+ return 0;
171
+ }
172
+
173
+ static inline char * LSAPI_GetQueryString_r( LSAPI_Request * pReq )
174
+ {
175
+ if ( pReq )
176
+ return pReq->m_pQueryString;
177
+ return NULL;
178
+ }
179
+
180
+
181
+ static inline char * LSAPI_GetScriptFileName_r( LSAPI_Request * pReq )
182
+ {
183
+ if ( pReq )
184
+ return pReq->m_pScriptFile;
185
+ return NULL;
186
+ }
187
+
188
+
189
+ static inline char * LSAPI_GetScriptName_r( LSAPI_Request * pReq )
190
+ {
191
+ if ( pReq )
192
+ return pReq->m_pScriptName;
193
+ return NULL;
194
+ }
195
+
196
+
197
+ static inline char * LSAPI_GetRequestMethod_r( LSAPI_Request * pReq)
198
+ {
199
+ if ( pReq )
200
+ return pReq->m_pRequestMethod;
201
+ return NULL;
202
+ }
203
+
204
+
205
+
206
+ static inline int LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq )
207
+ {
208
+ if ( pReq )
209
+ return pReq->m_pHeader->m_reqBodyLen;
210
+ return -1;
211
+ }
212
+
213
+ static inline int LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq )
214
+ {
215
+ if ( pReq )
216
+ return pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
217
+ return -1;
218
+ }
219
+
220
+
221
+ int LSAPI_Is_Listen(void);
222
+
223
+ static inline int LSAPI_Accept( void )
224
+ { return LSAPI_Accept_r( &g_req ); }
225
+
226
+ static inline int LSAPI_Finish(void)
227
+ { return LSAPI_Finish_r( &g_req ); }
228
+
229
+ static inline char * LSAPI_GetHeader( int headerIndex )
230
+ { return LSAPI_GetHeader_r( &g_req, headerIndex ); }
231
+
232
+ static inline int LSAPI_ForeachHeader( LSAPI_CB_EnvHandler fn, void * arg )
233
+ { return LSAPI_ForeachHeader_r( &g_req, fn, arg ); }
234
+
235
+ static inline int LSAPI_ForeachEnv( LSAPI_CB_EnvHandler fn, void * arg )
236
+ { return LSAPI_ForeachEnv_r( &g_req, fn, arg ); }
237
+
238
+ static inline int LSAPI_ForeachSpecialEnv( LSAPI_CB_EnvHandler fn, void * arg )
239
+ { return LSAPI_ForeachSpecialEnv_r( &g_req, fn, arg ); }
240
+
241
+ static inline char * LSAPI_GetEnv( const char * name )
242
+ { return LSAPI_GetEnv_r( &g_req, name ); }
243
+
244
+ static inline char * LSAPI_GetQueryString()
245
+ { return LSAPI_GetQueryString_r( &g_req ); }
246
+
247
+ static inline char * LSAPI_GetScriptFileName()
248
+ { return LSAPI_GetScriptFileName_r( &g_req ); }
249
+
250
+ static inline char * LSAPI_GetScriptName()
251
+ { return LSAPI_GetScriptName_r( &g_req ); }
252
+
253
+ static inline char * LSAPI_GetRequestMethod()
254
+ { return LSAPI_GetRequestMethod_r( &g_req ); }
255
+
256
+ static inline int LSAPI_GetReqBodyLen()
257
+ { return LSAPI_GetReqBodyLen_r( &g_req ); }
258
+
259
+ static inline int LSAPI_GetReqBodyRemain()
260
+ { return LSAPI_GetReqBodyRemain_r( &g_req ); }
261
+
262
+ static inline int LSAPI_ReadReqBody( char * pBuf, int len )
263
+ { return LSAPI_ReadReqBody_r( &g_req, pBuf, len ); }
264
+
265
+ static inline int LSAPI_FinalizeRespHeaders(void)
266
+ { return LSAPI_FinalizeRespHeaders_r( &g_req ); }
267
+
268
+ static inline int LSAPI_Write( const char * pBuf, int len )
269
+ { return LSAPI_Write_r( &g_req, pBuf, len ); }
270
+
271
+ static inline int LSAPI_Write_Stderr( const char * pBuf, int len )
272
+ { return LSAPI_Write_Stderr_r( &g_req, pBuf, len ); }
273
+
274
+ static inline int LSAPI_Flush()
275
+ { return LSAPI_Flush_r( &g_req ); }
276
+
277
+ static inline int LSAPI_AppendRespHeader( char * pBuf, int len )
278
+ { return LSAPI_AppendRespHeader_r( &g_req, pBuf, len ); }
279
+
280
+ static inline int LSAPI_SetRespStatus( int code )
281
+ { return LSAPI_SetRespStatus_r( &g_req, code ); }
282
+
283
+
284
+ #if defined (c_plusplus) || defined (__cplusplus)
285
+ }
286
+ #endif
287
+
288
+
289
+ #endif
290
+
291
+
292
+
293
+
294
+
295
+
296
+
@@ -0,0 +1,579 @@
1
+
2
+ #include "ruby.h"
3
+
4
+ #include "lsapilib.h"
5
+ #include <errno.h>
6
+ #include <netinet/in.h>
7
+ #include <netinet/tcp.h>
8
+ #include <signal.h>
9
+ #include <sys/socket.h>
10
+ #include <sys/wait.h>
11
+
12
+ //RUBY_EXTERN VALUE ruby_errinfo;
13
+ RUBY_EXTERN VALUE rb_stdin;
14
+ RUBY_EXTERN VALUE rb_stdout;
15
+ #if RUBY_VERSION_CODE < 180
16
+ RUBY_EXTERN VALUE rb_defout;
17
+ #endif
18
+
19
+ static VALUE orig_stdin;
20
+ static VALUE orig_stdout;
21
+ #if RUBY_VERSION_CODE < 180
22
+ static VALUE orig_defout;
23
+ #endif
24
+
25
+ static VALUE orig_env;
26
+
27
+ static VALUE lsapi_env;
28
+
29
+ static VALUE lsapi_objrefs;
30
+
31
+ typedef struct lsapi_data
32
+ {
33
+ LSAPI_Request * req;
34
+ VALUE env;
35
+ }lsapi_data;
36
+
37
+
38
+ static VALUE cLSAPI;
39
+
40
+ static VALUE s_req = Qnil;
41
+ static lsapi_data * s_req_data;
42
+
43
+ static int s_children = 0;
44
+ static int s_cur_children = 0;
45
+
46
+ static void lsapi_ruby_setenv(const char *name, const char *value)
47
+ {
48
+ if (!name) return;
49
+
50
+ if (value && *value)
51
+ ruby_setenv(name, value);
52
+ else
53
+ ruby_unsetenv(name);
54
+ }
55
+
56
+
57
+
58
+ static void lsapi_mark( lsapi_data * data )
59
+ {
60
+ rb_gc_mark( data->env );
61
+ }
62
+
63
+ static void lsapi_free_data( lsapi_data * data )
64
+ {
65
+ free( data );
66
+ }
67
+
68
+ static int add_env( const char * pKey, int keyLen, const char * pValue, int valLen,
69
+ void * arg )
70
+ {
71
+ //lsapi_ruby_setenv(pKey, pValue );
72
+ rb_hash_aset( lsapi_env,rb_tainted_str_new2(pKey),
73
+ rb_tainted_str_new2(pValue));
74
+ return 1;
75
+ }
76
+
77
+
78
+ static void clear_env()
79
+ {
80
+ rb_funcall( lsapi_env, rb_intern( "clear" ), 0 );
81
+ }
82
+
83
+ static void setup_cgi_env( lsapi_data * data )
84
+ {
85
+
86
+ clear_env();
87
+
88
+ LSAPI_ForeachHeader_r( data->req, add_env, data );
89
+ LSAPI_ForeachEnv_r( data->req, add_env, data );
90
+
91
+ }
92
+
93
+
94
+
95
+ static int s_stop;
96
+ void lsapi_cleanup(int signal)
97
+ {
98
+ s_stop = signal;
99
+ }
100
+
101
+ void lsapi_sigchild( int signal )
102
+ {
103
+ int status, pid;
104
+ while( 1 )
105
+ {
106
+ pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
107
+ if ( pid <= 0 )
108
+ {
109
+ break;
110
+ }
111
+
112
+ }
113
+
114
+ }
115
+
116
+ static int lsapi_fork_child()
117
+ {
118
+ struct sigaction act, old_term, old_quit, old_int, old_usr1, old_child;
119
+
120
+ char achPeer[128];
121
+ socklen_t len;
122
+ int nodelay = 1;
123
+
124
+ setsid();
125
+
126
+ act.sa_flags = 0;
127
+ act.sa_handler = lsapi_sigchild;
128
+ if( sigaction( SIGCHLD, &act, &old_child ) )
129
+ {
130
+ perror( "Can't set signal handler for SIGCHILD" );
131
+ return -1;
132
+ }
133
+
134
+ /* Set up handler to kill children upon exit */
135
+ act.sa_flags = 0;
136
+ act.sa_handler = lsapi_cleanup;
137
+ if( sigaction( SIGTERM, &act, &old_term ) ||
138
+ sigaction( SIGINT, &act, &old_int ) ||
139
+ sigaction( SIGUSR1, &act, &old_usr1 ) ||
140
+ sigaction( SIGQUIT, &act, &old_quit ))
141
+ {
142
+ perror( "Can't set signals" );
143
+ return -1;
144
+ }
145
+ s_stop = 0;
146
+ while( !s_stop )
147
+ {
148
+ len = sizeof( achPeer );
149
+ g_req.m_fd = accept( g_req.m_fdListen,
150
+ (struct sockaddr *)&achPeer, &len );
151
+ if ( g_req.m_fd != -1 )
152
+ {
153
+ if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
154
+ {
155
+ setsockopt(g_req.m_fd, IPPROTO_TCP, TCP_NODELAY,
156
+ (char *)&nodelay, sizeof(nodelay));
157
+ }
158
+ int pid = fork();
159
+ if ( !pid )
160
+ {
161
+ close( g_req.m_fdListen );
162
+ g_req.m_fdListen = -1;
163
+
164
+ /* don't catch our signals */
165
+ sigaction( SIGCHLD, &old_child, 0 );
166
+ sigaction( SIGTERM, &old_term, 0 );
167
+ sigaction( SIGQUIT, &old_quit, 0 );
168
+ sigaction( SIGINT, &old_int, 0 );
169
+ sigaction( SIGUSR1, &old_usr1, 0 );
170
+ return 0;
171
+ }
172
+ else if ( pid == -1 )
173
+ {
174
+ perror( "fork() failed" );
175
+ return -1;
176
+ }
177
+ else
178
+ {
179
+ close( g_req.m_fd );
180
+ g_req.m_fd = -1;
181
+ }
182
+ }
183
+ else
184
+ {
185
+ if (( errno == EINTR )||( errno == EAGAIN))
186
+ continue;
187
+ perror( "accept() failed" );
188
+ return -1;
189
+ }
190
+ }
191
+ kill( -getpgrp(), SIGUSR1 );
192
+ return -1;
193
+
194
+ }
195
+
196
+ static VALUE lsapi_s_accept( VALUE self )
197
+ {
198
+ // lsapi_data * req_data;
199
+ // VALUE req;
200
+ fd_set readfds;
201
+ int fd;
202
+ int ret;
203
+
204
+ LSAPI_Finish_r( &g_req );
205
+ if ( s_children )
206
+ {
207
+ if ( g_req.m_fdListen != -1 )
208
+ if ( lsapi_fork_child() == -1 )
209
+ return Qnil;
210
+ }
211
+ if ( g_req.m_fd != -1 )
212
+ {
213
+ fd = g_req.m_fd;
214
+ }
215
+ else if ( g_req.m_fdListen != -1 )
216
+ fd = g_req.m_fdListen;
217
+ else
218
+ return Qnil;
219
+
220
+ FD_ZERO( &readfds );
221
+ FD_SET( fd, &readfds );
222
+
223
+ if (rb_thread_select(fd+1, &readfds, NULL, NULL, NULL) < 1)
224
+ {
225
+ return Qnil;
226
+ }
227
+
228
+ ret = LSAPI_Accept_r( &g_req );
229
+
230
+ if ( !ret )
231
+ {
232
+ // req = Data_Make_Struct( self, lsapi_data, lsapi_mark, free, req_data );
233
+ // s_req = req;
234
+ // req_data->req = &g_req;
235
+ // rb_stdin = rb_stdout = req;
236
+ //#if RUBY_VERSION_CODE < 180
237
+ // rb_defout = req;
238
+ //#endif
239
+ setup_cgi_env( s_req_data );
240
+ return s_req;
241
+ }
242
+ return Qnil;
243
+ }
244
+
245
+
246
+ static int chdir_file( const char * pFile )
247
+ {
248
+ char * p = strrchr( pFile, '/' );
249
+ int ret;
250
+ if ( !p )
251
+ return -1;
252
+ *p = 0;
253
+ ret = chdir( pFile );
254
+ *p = '/';
255
+ return ret;
256
+ }
257
+
258
+ static VALUE lsapi_eval_string_wrap(VALUE self, VALUE str)
259
+ {
260
+ if (rb_safe_level() >= 4)
261
+ {
262
+ Check_Type(str, T_STRING);
263
+ }
264
+ else
265
+ {
266
+ Check_SafeStr(str);
267
+ }
268
+ return rb_eval_string_wrap(StringValuePtr(str), NULL);
269
+ }
270
+
271
+ static VALUE lsapi_process( VALUE self )
272
+ {
273
+ lsapi_data *data;
274
+ const char * pScriptPath;
275
+ Data_Get_Struct(self,lsapi_data, data);
276
+ pScriptPath = LSAPI_GetScriptFileName_r( data->req );
277
+ // if ( chdir_file( pScriptPath ) == -1 )
278
+ // {
279
+ // lsapi_send_error( 404 );
280
+ // }
281
+ // rb_load_file( pScriptPath );
282
+ return Qnil;
283
+ }
284
+
285
+
286
+ static VALUE lsapi_putc(VALUE self, VALUE c)
287
+ {
288
+ char ch = NUM2CHR(c);
289
+ // lsapi_data *data;
290
+ // Data_Get_Struct(self,lsapi_data, data);
291
+ if ( LSAPI_Write_r( &g_req, &ch, 1 ) == 1 )
292
+ return c;
293
+ else
294
+ return INT2NUM( EOF );
295
+ }
296
+
297
+
298
+ static VALUE lsapi_write( VALUE self, VALUE str )
299
+ {
300
+ lsapi_data *data;
301
+ int len;
302
+ // Data_Get_Struct(self,lsapi_data, data);
303
+ // len = LSAPI_Write_r( data->req, RSTRING(str)->ptr, RSTRING(str)->len );
304
+ if (TYPE(str) != T_STRING)
305
+ str = rb_obj_as_string(str);
306
+ len = LSAPI_Write_r( &g_req, RSTRING(str)->ptr, RSTRING(str)->len );
307
+ return INT2NUM( len );
308
+ }
309
+
310
+ static VALUE lsapi_print( int argc, VALUE *argv, VALUE out )
311
+ {
312
+ int i;
313
+ VALUE line;
314
+
315
+ /* if no argument given, print `$_' */
316
+ if (argc == 0)
317
+ {
318
+ argc = 1;
319
+ line = rb_lastline_get();
320
+ argv = &line;
321
+ }
322
+ for (i = 0; i<argc; i++)
323
+ {
324
+ if (!NIL_P(rb_output_fs) && i>0)
325
+ {
326
+ lsapi_write(out, rb_output_fs);
327
+ }
328
+ switch (TYPE(argv[i]))
329
+ {
330
+ case T_NIL:
331
+ lsapi_write(out, rb_str_new2("nil"));
332
+ break;
333
+ default:
334
+ lsapi_write(out, argv[i]);
335
+ break;
336
+ }
337
+ }
338
+ if (!NIL_P(rb_output_rs))
339
+ {
340
+ lsapi_write(out, rb_output_rs);
341
+ }
342
+
343
+ return Qnil;
344
+ }
345
+
346
+ static VALUE lsapi_printf(int argc, VALUE *argv, VALUE out)
347
+ {
348
+ lsapi_write(out, rb_f_sprintf(argc, argv));
349
+ return Qnil;
350
+ }
351
+
352
+ static VALUE lsapi_puts _((int, VALUE*, VALUE));
353
+
354
+ static VALUE lsapi_puts_ary(VALUE ary, VALUE out)
355
+ {
356
+ VALUE tmp;
357
+ int i;
358
+
359
+ for (i=0; i<RARRAY(ary)->len; i++)
360
+ {
361
+ tmp = RARRAY(ary)->ptr[i];
362
+ if (rb_inspecting_p(tmp))
363
+ {
364
+ tmp = rb_str_new2("[...]");
365
+ }
366
+ lsapi_puts(1, &tmp, out);
367
+ }
368
+ return Qnil;
369
+ }
370
+
371
+ static VALUE lsapi_puts(int argc, VALUE *argv, VALUE out)
372
+ {
373
+ int i;
374
+ VALUE line;
375
+
376
+ /* if no argument given, print newline. */
377
+ if (argc == 0)
378
+ {
379
+ lsapi_write(out, rb_default_rs);
380
+ return Qnil;
381
+ }
382
+ for (i=0; i<argc; i++)
383
+ {
384
+ switch (TYPE(argv[i]))
385
+ {
386
+ case T_NIL:
387
+ line = rb_str_new2("nil");
388
+ break;
389
+ case T_ARRAY:
390
+ rb_protect_inspect(lsapi_puts_ary, argv[i], out);
391
+ continue;
392
+ default:
393
+ line = argv[i];
394
+ break;
395
+ }
396
+ line = rb_obj_as_string(line);
397
+ lsapi_write(out, line);
398
+ if (RSTRING(line)->ptr[RSTRING(line)->len-1] != '\n')
399
+ {
400
+ lsapi_write(out, rb_default_rs);
401
+ }
402
+ }
403
+
404
+ return Qnil;
405
+ }
406
+
407
+
408
+ static VALUE lsapi_addstr(VALUE out, VALUE str)
409
+ {
410
+ lsapi_write(out, str);
411
+ return out;
412
+ }
413
+
414
+ static VALUE lsapi_flush( VALUE self )
415
+ {
416
+ //lsapi_data *data;
417
+ //Data_Get_Struct(self,lsapi_data, data);
418
+ LSAPI_Flush_r( &g_req );
419
+ return Qnil;
420
+ }
421
+
422
+ static VALUE lsapi_getc( VALUE self )
423
+ {
424
+ char ch;
425
+ //lsapi_data *data;
426
+ //Data_Get_Struct(self,lsapi_data, data);
427
+ LSAPI_ReadReqBody_r( &g_req, &ch, 1 );
428
+ return INT2NUM( (int)ch );
429
+ }
430
+
431
+
432
+ static VALUE lsapi_read(int argc, VALUE *argv, VALUE self)
433
+ {
434
+ VALUE str;
435
+ lsapi_data *data;
436
+ int n;
437
+ int remain;
438
+ char buff[8192];
439
+
440
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self))
441
+ {
442
+ rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
443
+ }
444
+
445
+ Data_Get_Struct(self, lsapi_data, data);
446
+
447
+ remain = LSAPI_GetReqBodyRemain();
448
+ if ( remain <= 0 )
449
+ return Qnil;
450
+ if (argc != 0)
451
+ {
452
+ n = NUM2INT(argv[0]);
453
+ if ( remain > n )
454
+ remain = n;
455
+ }
456
+ str = rb_str_buf_new( remain );
457
+ OBJ_TAINT(str);
458
+ while( remain > 0 )
459
+ {
460
+ n = LSAPI_ReadReqBody_r(data->req, buff,
461
+ (remain > 8192)?8192:remain );
462
+ if ( n > 0 )
463
+ {
464
+ rb_str_buf_cat( str, buff, n );
465
+ remain -= n;
466
+ }
467
+ else if ( n <= 0 )
468
+ {
469
+ //FIXME: broken connection
470
+ break;
471
+ }
472
+ }
473
+ return str;
474
+ }
475
+
476
+ static VALUE lsapi_eof(VALUE self)
477
+ {
478
+ // lsapi_data *data;
479
+ //
480
+ // if (rb_safe_level() >= 4 && !OBJ_TAINTED(self))
481
+ // {
482
+ // rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
483
+ // }
484
+ // Data_Get_Struct(self, lsapi_data, data);
485
+ return (LSAPI_GetReqBodyRemain( &g_req ) <= 0) ? Qtrue : Qfalse;
486
+ }
487
+
488
+ static VALUE lsapi_binmode(VALUE self)
489
+ {
490
+ // if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
491
+ // rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
492
+ // }
493
+ return self;
494
+ }
495
+
496
+ static VALUE lsapi_isatty(VALUE self)
497
+ {
498
+ // if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
499
+ // rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
500
+ // }
501
+ return Qfalse;
502
+ }
503
+
504
+ static VALUE lsapi_sync(VALUE self)
505
+ {
506
+ // if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
507
+ // rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
508
+ // }
509
+ return Qfalse;
510
+ }
511
+
512
+ static VALUE lsapi_setsync(VALUE self,VALUE sync)
513
+ {
514
+ // if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
515
+ // rb_raise(rb_eSecurityError, "Insecure: operation on untainted IO");
516
+ // }
517
+ return Qfalse;
518
+ }
519
+
520
+ void Init_lsapi()
521
+ {
522
+ char * p = getenv( "LSAPI_CHILDREN" );
523
+ if ( p )
524
+ {
525
+ s_children = atoi( p );
526
+ }
527
+
528
+ orig_stdin = rb_stdin;
529
+ orig_stdout = rb_stdout;
530
+ #if RUBY_VERSION_CODE < 180
531
+ orig_defout = rb_defout;
532
+ #endif
533
+ orig_env = rb_const_get( rb_cObject, rb_intern("ENV") );
534
+ // lsapi_env = orig_env;
535
+ lsapi_env = rb_hash_new();
536
+ //redefine ENV using a hash table, should be faster than char **environment
537
+ rb_define_global_const("ENV", lsapi_env);
538
+
539
+ LSAPI_Init();
540
+
541
+ rb_define_global_function("eval_string_wrap", lsapi_eval_string_wrap, 1);
542
+
543
+ cLSAPI = rb_define_class("LSAPI", rb_cObject);
544
+ rb_define_singleton_method(cLSAPI, "accept", lsapi_s_accept, 0);
545
+
546
+ rb_define_method(cLSAPI, "process", lsapi_process, 0 );
547
+ //rb_define_method(cLSAPI, "initialize", lsapi_initialize, 0);
548
+ rb_define_method(cLSAPI, "putc", lsapi_putc, 1);
549
+ rb_define_method(cLSAPI, "write", lsapi_write, 1);
550
+ rb_define_method(cLSAPI, "print", lsapi_print, -1);
551
+ rb_define_method(cLSAPI, "printf", lsapi_printf, -1);
552
+ rb_define_method(cLSAPI, "puts", lsapi_puts, -1);
553
+ rb_define_method(cLSAPI, "<<", lsapi_addstr, 1);
554
+ rb_define_method(cLSAPI, "flush", lsapi_flush, 0);
555
+ rb_define_method(cLSAPI, "getc", lsapi_getc, 0);
556
+ //rb_define_method(cLSAPI, "ungetc", lsapi_ungetc, 1);
557
+ //rb_define_method(cLSAPI, "gets", lsapi_gets, 0);
558
+ rb_define_method(cLSAPI, "read", lsapi_read, -1);
559
+ rb_define_method(cLSAPI, "eof", lsapi_eof, 0);
560
+ rb_define_method(cLSAPI, "eof?", lsapi_eof, 0);
561
+ // rb_define_method(cLSAPI, "close", lsapi_close, 0);
562
+ // rb_define_method(cLSAPI, "closed?", lsapi_closed, 0);
563
+ rb_define_method(cLSAPI, "binmode", lsapi_binmode, 0);
564
+ //rb_define_method(cLSAPI, "isatty", lsapi_isatty, 0);
565
+ //rb_define_method(cLSAPI, "tty?", lsapi_isatty, 0);
566
+ rb_define_method(cLSAPI, "sync", lsapi_sync, 0);
567
+ rb_define_method(cLSAPI, "sync=", lsapi_setsync, 1);
568
+
569
+ s_req = Data_Make_Struct( cLSAPI, lsapi_data, lsapi_mark, free, s_req_data );
570
+ s_req_data->req = &g_req;
571
+ rb_stdin = rb_stdout = s_req;
572
+ #if RUBY_VERSION_CODE < 180
573
+ rb_defout = s_req;
574
+ #endif
575
+ rb_global_variable(&s_req );
576
+
577
+ return;
578
+ }
579
+