mycgi.c
最終更新:2009/12/16
001: /* 002: * mycgi.c 003: * CGI スクリプトを処理する関数 004: */ 005: 006: #include "apr_general.h" 007: #include "apr_file_io.h" 008: #include "apr_errno.h" 009: #include "apr_tables.h" 010: #include "apr_buckets.h" 011: #include "apr_strings.h" 012: #include "apr_thread_proc.h" 013: #include "mybb.h" 014: #include "mycgi.h" 015: 016: /* 017: * ファイル名のディレクトリ部分を返す関数 018: * '/' がないときは "" を返す。 019: * ファイル名がヌルの時はヌルを返す。 020: */ 021: 022: char *get_dir( 023: char *filename 024: , apr_pool_t *pool 025: ) { 026: char *s = NULL; 027: if (!filename || !pool) 028: return NULL; 029: 030: s = strrchr(filename, '/'); 031: if (s) { 032: return apr_pstrndup(pool, filename, s-filename); 033: } 034: return ""; 035: } 036: 037: /* 038: * 返り値: 039: * 1: 成功 040: * 0: 失敗 041: */ 042: 043: int invoke_cgi (cgi_ctx *cctx) { 044: apr_status_t rv; 045: apr_proc_t proc; 046: char **args = NULL; 047: char **env = NULL; 048: apr_procattr_t *proc_attr = NULL; 049: 050: if (!cctx || ! cctx->pool) { 051: return 0; 052: } 053: 054: /* 引数配列作成 */ 055: 056: { 057: args = (char**)apr_palloc(cctx->pool, sizeof(char*)*4); 058: args[0] = cctx->prog_name; 059: args[1] = apr_pstrcat(cctx->pool, "-x", get_dir(cctx->script_name, cctx->pool), NULL); 060: args[2] = cctx->script_name; 061: args[3] = NULL; /* 最後はヌル */ 062: } 063: 064: /* 環境変数配列作成 */ 065: 066: { 067: int i=0; 068: const apr_array_header_t *tarr = apr_table_elts(cctx->env_tab); 069: const apr_table_entry_t *telts = (const apr_table_entry_t*)tarr->elts; 070: env = (char**)apr_palloc(cctx->pool, sizeof(char*)*(tarr->nelts+1)); 071: for (i=0; i<tarr->nelts; i++) { 072: env[i] = apr_pstrcat(cctx->pool, telts[i].key, "=", telts[i].val, NULL); 073: } 074: env[i] = NULL; /* 最後はヌル */ 075: } 076: 077: /* 子プロセスの属性情報生成 */ 078: 079: rv=apr_procattr_create(&proc_attr, cctx->pool); 080: if (APR_SUCCESS != rv) { 081: goto _FINALLY_; 082: } 083: 084: /* 子プロセスのコマンドタイプ設定 */ 085: 086: rv=apr_procattr_cmdtype_set(proc_attr, APR_PROGRAM); 087: if (APR_SUCCESS != rv) { 088: goto _FINALLY_; 089: } 090: 091: /* 子プロセスのパイプ準備 */ 092: 093: rv=apr_procattr_io_set(proc_attr, (cctx->clen>0)?APR_FULL_BLOCK:APR_NO_PIPE, APR_FULL_BLOCK, APR_NO_PIPE); 094: if (APR_SUCCESS != rv) { 095: goto _FINALLY_; 096: } 097: 098: /* 子プロセスの生成 */ 099: 100: rv = apr_proc_create(&proc, cctx->prog_name, (const char*const*)args, (const char*const*)env, proc_attr, cctx->pool); 101: if (APR_SUCCESS!=rv) { 102: goto _FINALLY_; 103: } 104: 105: /* 子プロセスへの送信 */ 106: 107: if (cctx->clen >0 && cctx->bbin && proc.in) { 108: /* cctx->bbin から proc.in へ */ 109: /* 110: apr_bucket_brigade *tmp_bb = apr_brigade_create(cctx->pool, cctx->bbin->bucket_alloc); 111: if (move_bytes_from_bb (cctx->bbin, cctx->clen, tmp_bb)) 112: write_from_bb_to_fp(tmp_bb, proc.in); 113: */ 114: move_bytes_from_bb_to_fp(cctx->bbin, cctx->clen, proc.in); 115: apr_file_close(proc.in); 116: } 117: 118: 119: /* 子プロセスからの受信 */ 120: 121: if (proc.out) { 122: /* proc.out から cctx->bbout へ */ 123: #define BUF_SIZE 1024 124: char buf[BUF_SIZE]; 125: apr_size_t len=0; 126: while (1) { 127: if(APR_EOF == apr_file_eof(proc.out)) { 128: break; 129: } 130: len = BUF_SIZE; 131: if (APR_SUCCESS == apr_file_read(proc.out, buf, &len)) { 132: apr_brigade_write(cctx->bbout, NULL, NULL, buf, len); 133: } 134: } 135: apr_file_close(proc.out); 136: } 137: 138: 139: /* 子プロセスの終了待ち */ 140: 141: { 142: int exitcode=0; 143: apr_exit_why_e why; 144: rv = apr_proc_wait(&proc, &exitcode, &why, APR_WAIT); 145: if (APR_CHILD_DONE == rv) { 146: rv = APR_SUCCESS; 147: } 148: } 149: 150: _FINALLY_: 151: 152: if(APR_SUCCESS != rv) { 153: char error_buf[256]; 154: fprintf(stderr, "ERROR: %s\n", 155: apr_strerror(rv, error_buf, sizeof(error_buf))); 156: return 0; 157: } 158: 159: return 1; 160: }
KAKU PROJECT (2009) |