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) |