kcgi.c

最終更新:2009/12/16

kcgi.c

001: /*
002:  * kcgi2.c
003:  * CGI スクリプトを処理する例
004:  */
005:   
006: #include "apr_general.h"
007: #include "apr_lib.h"
008: #include "apr_file_io.h"
009: #include "apr_errno.h"
010: #include "apr_tables.h"
011: #include "apr_buckets.h"
012: #include "apr_strings.h"
013: #include "apr_thread_proc.h"
014: 
015: #include "mycgi.h"
016: #include "mybb.h"
017: #include "mystab.h"
018: 
019: #define DEFAULT_DOC_ROOT "d:/work/apr/work"
020: #define PERL_EXE_PATH "c:/perl/bin/perl.exe"
021: 
022: #define CGI_SCRIPT_LOGICAL_PATH "/cgi-bin/hoge.pl"
023: 
024: #define DEFAULT_PATH_ENV "c:/perl/bin"
025: 
026: /* サーバ情報 */
027: 
028: typedef struct _server_ctx {
029:   char * server_name;
030:   char * server_software;
031:   int port;
032:   
033:   char *doc_root;
034:   
035: } svr_ctx;
036: 
037: int apr_my_main (
038:   int ac
039:   , char **av
040:   , apr_file_t * astdin
041:   , apr_file_t * astdout
042:   , apr_file_t * astderr
043:   , apr_pool_t * pool
044: ) {
045: 
046:   apr_status_t rv;
047:   char error_buf[256];
048: 
049:   apr_pool_t *pool2 = NULL;
050:   cgi_ctx *cctx = NULL;
051:   svr_ctx *sctx = NULL;
052: 
053:   apr_table_t *headers = NULL;
054:   
055:   char *method = "POST";
056: /*
057:   char *method = "GET";
058: */
059: 
060:   char *query = "key=%7E%21@%23%24%25%5E%26*%28%29_%2B";
061: /*
062:   char *query = NULL;
063:   char *query = "abc=123&xyz=789";
064: */
065: 
066: /*
067:   char *postdata = NULL;
068: */
069:   char *postdata = "key1=val1&key2=val2&key3=val3";
070:   
071:   /* サーバ情報 */
072:   sctx = (svr_ctx*)apr_palloc(pool, sizeof(svr_ctx));
073:   sctx->server_name = "127.0.0.1";
074:   sctx->port = 80;
075:   sctx->server_software = "kcgi/1.0";
076:   sctx->doc_root = DEFAULT_DOC_ROOT;
077:   
078:   
079:   /* HTTP リクエスト情報 */
080:   
081:   headers = apr_table_make(pool, 10);
082:   apr_table_set(headers, "Host", sctx->server_name);
083:   apr_table_set(headers, "User-Agent", "Some_brawser/1.0");
084:   apr_table_set(headers, "Accept", "*/*");
085:   apr_table_set(headers, "Accept-Charset", "shift_jis, utf-8");
086:   apr_table_set(headers, "Accept-Language", "jp, en");
087:   apr_table_set(headers, "Accept-Encoding", "gzip,compress,deflate");
088:   
089:   if (!strcmp(method, "POST") && postdata) {
090:     apr_table_set(headers, "Content-Length", apr_itoa(pool, strlen(postdata)));
091:     apr_table_set(headers, "Content-Type", "application/x-www-form-urlencoded");
092:   }
093:   
094:   /* 子プロセス用メモリプール生成 */
095: 
096:   rv=apr_pool_create(&pool2, NULL);
097:   if (APR_SUCCESS != rv) {
098:     goto _FINALLY_;
099:   }
100:   
101:   /* CGIコンテクスト生成 */
102: 
103:   /* http://127.0.0.1/cgi-bin/hoge.pl?abc=123&xyz=789 */
104: 
105:   {
106:     apr_bucket_alloc_t *ba = apr_bucket_alloc_create(pool2);
107:     cctx = (cgi_ctx*)apr_palloc(pool2, sizeof(cgi_ctx));
108:     cctx->pool = pool2;
109:     cctx->prog_name = PERL_EXE_PATH;
110:     cctx->script_name = apr_pstrcat(cctx->pool, sctx->doc_root, CGI_SCRIPT_LOGICAL_PATH, NULL);
111: 
112:     cctx->clen = 0;
113:     
114:     if (!strcmp(method, "POST") && postdata) {
115:       cctx->clen = strlen(postdata);
116:       cctx->bbin = apr_brigade_create(cctx->pool, ba);
117:       apr_brigade_write(cctx->bbin, NULL, NULL, postdata, cctx->clen);
118:     } else {
119:       cctx->bbin = NULL;
120:     }
121:     cctx->bbout = apr_brigade_create(cctx->pool, ba);
122:     
123:     cctx->env_tab = apr_table_make(cctx->pool, 17);
124:     apr_table_set(cctx->env_tab, "PATH", DEFAULT_PATH_ENV);
125:     apr_table_set(cctx->env_tab, "SERVER_SOFTWARE", sctx->server_software);
126:     apr_table_set(cctx->env_tab, "SERVER_NAME", sctx->server_name);
127:     apr_table_set(cctx->env_tab, "GATEWAY_INTERFACE", "CGI/1.1");
128:     apr_table_set(cctx->env_tab, "SERVER_PROTOCOL", "HTTP/1.1");
129:     apr_table_set(cctx->env_tab, "SERVER_PORT", apr_itoa(cctx->pool, sctx->port));
130:     apr_table_set(cctx->env_tab, "REQUEST_METHOD", method);
131: /*
132:     apr_table_set(cctx->env_tab, "PATH_INFO", "/");
133:     apr_table_set(cctx->env_tab, "PATH_TRANSLATED", "");
134: */
135: 
136:     apr_table_set(cctx->env_tab, "SCRIPT_NAME", "/cgi-bin/hoge.pl");
137: 
138:     if(query) {
139:       apr_table_set(cctx->env_tab, "QUERY_STRING", query);
140:     }
141:     apr_table_set(cctx->env_tab, "REMOTE_HOST", "127.0.0.1");
142:     apr_table_set(cctx->env_tab, "REMOTE_ADDR", "127.0.0.1");
143: /*
144:     apr_table_set(cctx->env_tab, "AUTH_TYPE", "basic");
145:     apr_table_set(cctx->env_tab, "REMOTE_USER", "nemo");
146: */
147: /*
148:     apr_table_set(cctx->env_tab, "REMOTE_IDENT", "");
149: */
150:     if (cctx->clen > 0) {
151:       apr_table_set(cctx->env_tab, "CONTENT_TYPE", "application/x-www-form-urlencoded");
152:       apr_table_set(cctx->env_tab, "CONTENT_LENGTH", apr_itoa(pool, cctx->clen));
153:     }
154: 
155: 
156:     /* HTTP リクエストのヘッダをセット
157:      * ヘッダ名の変換:
158:      * ・"HTTP_" の付加
159:      * ・ハイフン '-' はアンダースコア '_' に変換
160:      * ・大文字に変換
161:      */
162:     {
163:       int i=0;
164:       const apr_table_entry_t *telts;
165:       const apr_array_header_t *tarr = apr_table_elts(headers);
166:       telts = (const apr_table_entry_t*)tarr->elts;
167:       for (i = 0; i < tarr->nelts; i++) {
168:         char *s = NULL;
169:         char *key = apr_pstrcat(cctx->pool, "HTTP_", telts[i].key, NULL);
170:         for (s=key; *s; s++) {
171:           if (*s == '-') {
172:             *s = '_';
173:           } else {
174:             *s = apr_toupper(*s);
175:           }
176:         }
177:         apr_table_set(cctx->env_tab, key, telts[i].val);
178:       }
179:     }
180: 
181:   }
182:   
183:   /* CGI プロセスの処理 */
184:   
185:   {
186: 
187:     if (!invoke_cgi(cctx)) {
188:       goto _FINALLY_;
189:     }
190:   }
191:   
192:   if(read_entity_header_CRLF(cctx->bbout)) {
193:     apr_off_t len=0;
194:     apr_brigade_length(cctx->bbout, 1, &len);
195:     apr_file_printf(astdout, "Content-Length=[%d]\n", (int)len);
196:     write_from_bb_to_fp(cctx->bbout, astdout);
197:   }
198: 
199:   _FINALLY_:
200: 
201:   /* 子プロセス用メモリプールの解放 */
202:   
203:   if (pool2) {
204:     apr_pool_destroy(pool2);
205:     pool2 = NULL;
206:   }
207: 
208:   if (rv != APR_SUCCESS) {
209:     apr_file_printf(astderr, "ERROR: %s\n", apr_strerror(rv, error_buf, sizeof(error_buf)));
210:     apr_file_printf(astderr, "failed!\n");
211:     return 1; /* 異常終了 */
212:   }
213:   
214:   apr_file_printf(astdout, "\ndone.\n");
215: 
216:   return 0; /* 正常終了 */
217: 
218: } /* end of main */
Copyright (C) KAKU PROJECT (2009)KAKU PROJECT (2009)