/* * mycgi.c * CGI スクリプトを処理する関数 */ #include "apr_general.h" #include "apr_file_io.h" #include "apr_errno.h" #include "apr_tables.h" #include "apr_buckets.h" #include "apr_strings.h" #include "apr_thread_proc.h" #include "mybb.h" #include "mycgi.h" /* * ファイル名のディレクトリ部分を返す関数 * '/' がないときは "" を返す。 * ファイル名がヌルの時はヌルを返す。 */ char *get_dir( char *filename , apr_pool_t *pool ) { char *s = NULL; if (!filename || !pool) return NULL; s = strrchr(filename, '/'); if (s) { return apr_pstrndup(pool, filename, s-filename); } return ""; } /* * 返り値: * 1: 成功 * 0: 失敗 */ int invoke_cgi (cgi_ctx *cctx) { apr_status_t rv; apr_proc_t proc; char **args = NULL; char **env = NULL; apr_procattr_t *proc_attr = NULL; if (!cctx || ! cctx->pool) { return 0; } /* 引数配列作成 */ { args = (char**)apr_palloc(cctx->pool, sizeof(char*)*4); args[0] = cctx->prog_name; args[1] = apr_pstrcat(cctx->pool, "-x", get_dir(cctx->script_name, cctx->pool), NULL); args[2] = cctx->script_name; args[3] = NULL; /* 最後はヌル */ } /* 環境変数配列作成 */ { int i=0; const apr_array_header_t *tarr = apr_table_elts(cctx->env_tab); const apr_table_entry_t *telts = (const apr_table_entry_t*)tarr->elts; env = (char**)apr_palloc(cctx->pool, sizeof(char*)*(tarr->nelts+1)); for (i=0; inelts; i++) { env[i] = apr_pstrcat(cctx->pool, telts[i].key, "=", telts[i].val, NULL); } env[i] = NULL; /* 最後はヌル */ } /* 子プロセスの属性情報生成 */ rv=apr_procattr_create(&proc_attr, cctx->pool); if (APR_SUCCESS != rv) { goto _FINALLY_; } /* 子プロセスのコマンドタイプ設定 */ rv=apr_procattr_cmdtype_set(proc_attr, APR_PROGRAM); if (APR_SUCCESS != rv) { goto _FINALLY_; } /* 子プロセスのパイプ準備 */ rv=apr_procattr_io_set(proc_attr, (cctx->clen>0)?APR_FULL_BLOCK:APR_NO_PIPE, APR_FULL_BLOCK, APR_NO_PIPE); if (APR_SUCCESS != rv) { goto _FINALLY_; } /* 子プロセスの生成 */ rv = apr_proc_create(&proc, cctx->prog_name, (const char*const*)args, (const char*const*)env, proc_attr, cctx->pool); if (APR_SUCCESS!=rv) { goto _FINALLY_; } /* 子プロセスへの送信 */ if (cctx->clen >0 && cctx->bbin && proc.in) { /* cctx->bbin から proc.in へ */ /* apr_bucket_brigade *tmp_bb = apr_brigade_create(cctx->pool, cctx->bbin->bucket_alloc); if (move_bytes_from_bb (cctx->bbin, cctx->clen, tmp_bb)) write_from_bb_to_fp(tmp_bb, proc.in); */ move_bytes_from_bb_to_fp(cctx->bbin, cctx->clen, proc.in); apr_file_close(proc.in); } /* 子プロセスからの受信 */ if (proc.out) { /* proc.out から cctx->bbout へ */ #define BUF_SIZE 1024 char buf[BUF_SIZE]; apr_size_t len=0; while (1) { if(APR_EOF == apr_file_eof(proc.out)) { break; } len = BUF_SIZE; if (APR_SUCCESS == apr_file_read(proc.out, buf, &len)) { apr_brigade_write(cctx->bbout, NULL, NULL, buf, len); } } apr_file_close(proc.out); } /* 子プロセスの終了待ち */ { int exitcode=0; apr_exit_why_e why; rv = apr_proc_wait(&proc, &exitcode, &why, APR_WAIT); if (APR_CHILD_DONE == rv) { rv = APR_SUCCESS; } } _FINALLY_: if(APR_SUCCESS != rv) { char error_buf[256]; fprintf(stderr, "ERROR: %s\n", apr_strerror(rv, error_buf, sizeof(error_buf))); return 0; } return 1; }