TLPI memo 3
2.15 疑似端末
自分の端末はw
ででてきた、TTY
でわかる
vagrant@precise64:~$ w 12:53:33 up 0 min, 1 user, load average: 0.00, 0.00, 0.00 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT vagrant pts/0 10.0.2.2 12:53 0.00s 0.20s 0.00s w vagrant@precise64:~$ vagrant@precise64:~$ ls -la /dev/pts/0 crw--w---- 1 vagrant tty 136, 0 Jan 19 12:53 /dev/pts/0
3.1 システムコール
strace
にコマンドを渡すと実行されるシステムコールがドバドバ出る
strace ls .
こんなかんじで
execve("/bin/ls", ["ls", "."], [/* 18 vars */]) = 0 brk(0) = 0x10b8000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f723661d000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=18510, ...}) = 0 mmap(NULL, 18510, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7236618000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
標準関数(関数)とは
glibcに含まれるもの
「TLPI」を読んでく No.2
mmap()
仮想アドレス空間に領域を確保する
- ファイルマッピンク
- ファイルをメモリ領域にマップする
- その領域を書き換えると、ファイルも書き換わる
- 無名マッピング
- 対応するファイルは無い。
プロセス間通信
プロセスがお互いにやりとりする
- シグナル
- SIGなんとか
- パイプ(FIFO)
- プロセス間でのデータのやり取り
- socket
- プロセス間でのデータのやり取り
- ファイルロック
- 読み取り、書き込みロック
- メッセージキュー
- 非同期
- セマフォ
- 他のプロセスと共有している物へのアクセスを制御する
- 共有メモリ
- 複数のプロセスが同じ領域を見ていて、誰かが変えるとみんなも変わる
スレッド
プロセスが内部的に持つ実行単位
mod_mruby install してみた
なぜやるのか?
インフラエンジニアをやっていて、かゆいところに手が届かないことがたくさんあって
もどかしい思いをずっとしてきた。
でもいまは時代が変わったようで、自分でmoduleを作らなくても
チョイチョイっとかゆいところに手が届くそうだ
そうmrubyならね!
この流れ(あってる?)に乗り遅れるな!
で、matsumoto-r さん作の mod_mrubyを使ってみよう
親切にここに書かれていたので、この通りにする。
結果、test.rbが動くまではサクッとできる。 あとは何をしたいか。 ちょっとこれから考えてみよう。
以下やったログ
apacheいれとく
sudo yum install httpd.x86_64 sudo yum install httpd-devel.x86_64
mod_mrubyのsrcをもってくる
git clone git://github.com/matsumoto-r/mod_mruby.git
テストとビルド
cd mod_mruby
sh test.sh
sh build.sh
私はvagrant環境で試した 以下にビルド後の.soファイルができてた
ls -la /home/vagrant/mod_mruby/src/.libs/mod_mruby.so
これをコピってあげた。
cp /home/vagrant/mod_mruby/src/.libs/mod_mruby.so /usr/lib64/httpd/modules/ chown root: /usr/lib64/httpd/modules/mod_mruby.so
コンフもマニュアルのとおりに
[root@localhost mod_mruby]# cat /etc/httpd/conf.d/mruby.conf LoadModule mruby_module modules/mod_mruby.so <Location /mruby-test> mrubyHandlerMiddle /etc/httpd/conf.d/test.rb cache </Location>
予め準備されているものを読み込むべくコピー
cp -p test/test.rb /etc/httpd/conf.d/ chown root: /etc/httpd/conf.d/test.rb
apacheを起動
systemctl status httpd.service systemctl start httpd.service
curl してみた結果
[root@localhost mod_mruby]# curl http://127.0.0.1/mruby-test # mod_mruby Test Page __mod_mruby test start.__ ## Apache Class Test - Server: Apache - Apache version: Apache/2.4.6 (CentOS) - Apache build: Nov 19 2015 21:43:13 - module name: mod_mruby - module version: 1.13.10 - syslogger function: OK - errlogger function: OK - OK status = 0 - DECLINED status = -1 - HTTP_OK status = 200 - HTTP_SERVICE_UNAVAILABLE status = 503 ## Request Class Test - filename = /var/www/html/mruby-test - uri = /mruby-test - ---- request_rec changed ---- - filename = /var/www/html/index.html - uri = /index.html r.document_root: /var/www/html r.document_root: /tmp ## Server Class Test - document_root = /var/www/html - error_fname = logs/error_log - hostname = localhost.localdomain - timeout = 60000000 ## Connection Class Test - remote_ip 127.0.0.1 - local_ip 127.0.0.1 - keepalives = 0 ##Notes Class Test - memo = hello ## Env Class Test - AUTHOR = matsumoto_r - SERVER_SOFTWARE = Apache/2.4.6 (CentOS) - env hash size = 25 - env key = UNIQUE_ID val = VsMsFszCek7oPhdkOOPzNAAAAAM - env key = HTTP_USER_AGENT val = curl/7.29.0 - env key = HTTP_HOST val = 127.0.0.1 - env key = HTTP_ACCEPT val = */* - env key = PATH val = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin - env key = SERVER_SIGNATURE val = - env key = SERVER_SOFTWARE val = A p a c h e - env key = SERVER_NAME val = 127.0.0.1 - env key = SERVER_ADDR val = 127.0.0.1 - env key = SERVER_PORT val = 80 - env key = REMOTE_ADDR val = 127.0.0.1 - env key = DOCUMENT_ROOT val = /var/www/html - env key = REQUEST_SCHEME val = http - env key = CONTEXT_PREFIX val = - env key = CONTEXT_DOCUMENT_ROOT val = /var/www/html - env key = SERVER_ADMIN val = root@localhost - env key = SCRIPT_FILENAME val = /var/www/html/index.html - env key = REMOTE_PORT val = 57100 - env key = GATEWAY_INTERFACE val = CGI/1.1 - env key = SERVER_PROTOCOL val = HTTP/1.1 - env key = REQUEST_METHOD val = GET - env key = QUERY_STRING val = - env key = REQUEST_URI val = /mruby-test - env key = SCRIPT_NAME val = /index.html - env key = AUTHOR val = matsumoto_r ## Headers_in Class Test - Accept-Encoding = nil - Accept-Encoding = gzip - headers_in hash size = 4 - headers_in key = User-Agent val = curl/7.29.0 - headers_in key = Host val = 127.0.0.1 - headers_in key = Accept val = */* - headers_in key = Accept-Encoding val = gzip ## Headers_out Class Test - headers_out hash size = 0 ## Scoreboard Class Test - child pid = 15737 - thread limit = 1 - server limit = 256 - cpu load = 792739788800 - load avereage = [0, 0.0099999997764826, 0.090000003576279] - total kbyte = 3 - total access = 1 - restart time = 1.4556306719778e+15 - idle worker = 4 - busy worker = 1 - uptime = 710 - access counter = -1 - scoreboard status hash size = 1 - scoreboard key = 127.0.0.1 val = SERVER_GRACEFUL - scoreboard counter hash size = 11 - scoreboard key = SERVER_READY val = 4 - scoreboard key = SERVER_STARTING val = 0 - scoreboard key = SERVER_BUSY_READ val = 0 - scoreboard key = SERVER_BUSY_WRITE val = 1 - scoreboard key = SERVER_BUSY_KEEPALIVE val = 0 - scoreboard key = SERVER_BUSY_LOG val = 0 - scoreboard key = SERVER_BUSY_DNS val = 0 - scoreboard key = SERVER_CLOSING val = 0 - scoreboard key = SERVER_DEAD val = 251 - scoreboard key = SERVER_GRACEFUL val = 0 - scoreboard key = SERVER_IDLE_KILL val = 0 ## Finfo Class Test - permission = 1877 - filetype regular file = false - user = 0 - group = 0 - device = 64768 - inode = 35205976 - nlink = 2 - size = 6 - csize = 0 - atime = 1.447969437e+15 - mtime = 1.447969437e+15 - ctime = 1.4556292035898e+15 __Test Complete. Wellcome to mod_mruby world!!__
Cやってみよう #6
前年の続き
だいぶ間が空いてしまった。
2016年、restartです。
続けるように。
mod_vhost_maxclients.c
のソースを見ていきましょう。
174 for (i = 0; i < vhost_maxclients_server_limit; ++i) { 175 for (j = 0; j < vhost_maxclients_thread_limit; ++j) { 176 worker_score *ws_record = ap_get_scoreboard_worker(i, j); 177 #ifdef __APACHE24__ 178 char *client_ip = r->connection->client_ip; 179 #else 180 char *client_ip = r->connection->remote_ip; 181 #endif
- 174行目は
vhost_maxclients_server_limit
まで繰り返しの処理が開始 - 175行目は
vhost_maxclients_thread_limit
まで繰り返しの処理が開始- 例えば両方のlimitの値が10の場合は、
10*10=100
回、繰り返すわけですね。
- 例えば両方のlimitの値が10の場合は、
- 176行目が肝のようだ。
ap_get_scoreboard_worker
この処理で、apacheが持つscoreboardから値を取って
*ws_record
に値を入れている。
http://apache.org/server-status
↑のserver-statusをimageしとけばいいのだろうか。 - 178,180行目は、接続元のIPを取得している。
183 switch (ws_record->status) { 184 case SERVER_BUSY_READ: 185 case SERVER_BUSY_WRITE: 186 case SERVER_BUSY_KEEPALIVE: 187 case SERVER_BUSY_LOG: 188 case SERVER_BUSY_DNS: 189 case SERVER_CLOSING: 190 case SERVER_GRACEFUL:
ws_record->status
のstatusで分岐をおこない、以下の状態の時にカウントをしている
#define SERVER_BUSY_READ 3 /* Reading a client request */ #define SERVER_BUSY_WRITE 4 /* Processing a client request */ #define SERVER_BUSY_KEEPALIVE 5 /* Waiting for more requests via keepalive */ #define SERVER_BUSY_LOG 6 /* Logging the request */ #define SERVER_BUSY_DNS 7 /* Looking up a hostname */ #define SERVER_CLOSING 8 /* Closing the connection */ #define SERVER_GRACEFUL 9 /* server is gracefully finishing request */
ここからが本題なのです。
190 case SERVER_GRACEFUL: 191 /* check maxclients per vhost */ 192 if (strcmp(vhostport, ws_record->vhost) == 0) { 193 vhost_count++; 194 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "DEBUG: (increment %s): %d/%d", vhostport, 195 vhost_count, scfg->vhost_maxclients); 196 if (vhost_count > scfg->vhost_maxclients) { 197 if (scfg->dryrun > 0) { 198 ap_log_error( 199 APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, 200 "NOTICE: [DRY-RUN] [VHOST_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s", 201 vhostport, vhost_count, scfg->vhost_maxclients, client_ip, r->uri, r->filename); 202 } else { 203 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, 204 "NOTICE: [VHOST_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s", 205 vhostport, vhost_count, scfg->vhost_maxclients, client_ip, r->uri, r->filename); 206 } 207 return (scfg->dryrun > 0) ? DECLINED : HTTP_SERVICE_UNAVAILABLE; 208 } 209 210 /* check maxclients per ip in same vhost */ 211 if (scfg->vhost_maxclients_per_ip > 0) { 212 if (strcmp(client_ip, ws_record->client) == 0) { 213 ip_count++; 214 if (ip_count > scfg->vhost_maxclients_per_ip) { 215 if (scfg->dryrun > 0) { 216 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "NOTICE: [DRY-RUN] [CLIENT_COUNT] return " 217 "503 from %s : %d / %d client_ip: %s uri: " 218 "%s filename: %s", 219 vhostport, ip_count, scfg->vhost_maxclients_per_ip, client_ip, r->uri, r->filename); 220 } else { 221 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, 222 "NOTICE: [CLIENT_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s", 223 vhostport, ip_count, scfg->vhost_maxclients_per_ip, client_ip, r->uri, r->filename); 224 } 225 return (scfg->dryrun > 0) ? DECLINED : HTTP_SERVICE_UNAVAILABLE; 226 } 227 } 228 } 229 } 230 break;
- 192行目でリクエストの
hoge.com:80
とscoreboardとが一致していればvhost_count++
をインクリメント。 196行目で設定されているlimit値を超えているかの判定を行っている。
超えている場合、以下の処理を行う- 197行目でドライランかの判定を行い、それぞれでログを出力している
- 207行目でドライランであれば
DECLINED
ドライランでなければ、HTTP_SERVICE_UNAVAILABLE = 503
となる
211行目移行は、同一のvhostに対して同じIPからのアクセスを制御する
こんな感じで、このモジュールは書かれていることが分かった。
一旦、おわりー
Cも時間を割けばわかるものなのですね。。 つぎは何しよう。
Cやってみよう #5
先日の続き
有識者とはタイミングが合わず、今回も独自の視点からみてみましょう!
その前に、apache
に由来する部分を抑えようと思い立ちました。
request_rec
構造体というモノを軽く見てみましょう。
とおもってググったら素晴らしいサイトに出会いました
ここを見れば一発OK!
request_rec
はもう怖くない。
クライアントから送信された、リクエストの中身が見て取れますね!
ではこちら:mod_vhost_maxclients 続けましょう!
140 static int vhost_maxclients_handler(request_rec *r) 141 { 142 int i, j; 143 int vhost_count = 0; 144 int ip_count = 0; 145 char *vhostport; 146 vhost_maxclients_config *scfg = 147 (vhost_maxclients_config *)ap_get_module_config(r->server->module_config, &vhost_maxclients_module);
- 140行目は関数の定義
- 147行目は
ap_get_module_config
で設定を読み込んでいる- 読み込んでるものは、ここ(334〜345行目)に定義されているものであろう(詳細不明)
334 #ifdef __APACHE24__ 335 AP_DECLARE_MODULE(vhost_maxclients) = { 336 #else 337 module AP_MODULE_DECLARE_DATA vhost_maxclients_module = { 338 #endif 339 STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ 340 NULL, /* merge per-dir config structures */ 341 vhost_maxclients_create_server_config, /* create per-server config 342 structures */ 343 vhost_maxclients_create_server_merge_conf, /* merge per-server config structures */ 344 vhost_maxclients_cmds, /* table of config file commands */ 345 vhost_maxclients_register_hooks};
つぎー
149 if (!ap_is_initial_req(r)) { 150 return DECLINED; 151 } 152 153 if (scfg->vhost_maxclients <= 0) { 154 return DECLINED; 155 } 156 157 if (r->hostname == NULL) { 158 return DECLINED; 159 } 160 161 if (!ap_extended_status) { 162 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "DEBUG: only used when ExtendedStatus On"); 163 return DECLINED; 164 } 165 166 /* check ignore extesions */ 167 if (check_extension(r->filename, scfg->ignore_extensions)) { 168 return DECLINED; 169 }
- 149行目の
ap_is_initial_req
は以下の判定を行う- 最初のリクエストであれば、true
- リダイレクトだったりした場合は、false
ので、falseの場合は、DECLINED
処理終了(mod_vhost_maxclientsの処理終了)となる
- よってこの辺(149〜169行名)は、変数やリクエストの中身をチェックして、処理できない場合は処理終了としている。
つぎー
171 /* build vhostport name */ 172 vhostport = build_vhostport_name(r);
- 172行目は先週書いた
build_vhostport_name
からhoge.com:80
を取得してる
つぎー。
ここからがこのモジュールのメインの部分であろう。
が、長いので明日に!
Cやってみよう #4
先日の続き
おそろしい、C言語は恐ろしい。
たった10数行にも関わらず、頭に入ってこない。
俺の目と頭が連動しない...
慣れるしか無いのか!
112 static int check_extension(char *filename, apr_array_header_t *exts) 113 { 114 int i; 115 for (i = 0; i < exts->nelts; i++) { 116 const char *extension = ((char **)exts->elts)[i]; 117 ssize_t name_len = strlen(filename) - strlen(extension); 118 if (name_len >= 0 && strcmp(&filename[name_len], extension) == 0) 119 return 1; 120 } 121 return 0; 122 }
- 112行目で引数を2つもらう関数を定義してる。返り値は
int
- 115行目の
exts->nelts
は数値なのであろう。これは配列の要素数なんだろう。 - 116行目の
const char
は読み取り専用の文字列に配列の内容を入れているのだろう! - 116行目の
(char **)
これはなんだ?- Dereferencingとな
- 変数のアドレスから値を取得する
- Dereferencingとな
- 117行目の
ssize_t
は、書き込まれたバイト数,エラー時は-1
- 117行目はファイル名の文字数から配列の要素の文字数を引いて、
name_len
にいれとる。 - 118行目の
strcmp
は文字列比較 - 結果、この関数は
0
or1
を返す
次々
124 static char *build_vhostport_name(request_rec *r) 125 { 126 #ifdef __APACHE24__ 127 ssize_t vhostport_len; 128 char *vhostport; 129 130 vhostport_len = strlen(r->hostname) + sizeof(":65536"); 131 vhostport = apr_pcalloc(r->pool, vhostport_len); 132 apr_snprintf(vhostport, vhostport_len, "%s:%d", r->hostname, r->connection->local_addr->port); 133 134 return vhostport; 135 #else 136 return (char *)r->hostname; 137 #endif 138 }
- 124行目で引数を1つもらう関数を定義してる。返り値は
char
- 124行目の
request_rec
はapacheの持ってる構造体をrというアドレスに定義?してる #
はコメントアウトなの?- 130行目で
vhostport_len
にこの場合はvirtualhostの長さと65536のメモリサイズを足した値を返してる- よくわからん
- 131行目は
apr_pcalloc
で初期化してる - 132行目は
apr_snprintf
ぐぐってもわからん。 - 結局この関数は
hoge.com:80
みたいなものを返してるのではないだろうか。
ちょっと憶測が多くなってきて、ぐぐっても分からないので有識者に聞こう。。。
聞いたら更新しますからね!
Cやってみよう #3
先日の続き
偉大な先輩が言ってた
「時間があったら人のソースを読んで勉強しろ」
ということで、最近話題のソースを読んで勉強します。
お題はこちら:mod_vhost_maxclients
一つのapacheで複数のバーチャルホストを運用している場合は有用なのではないでしょうか!
C言語、勉強中ですので間違ってるかも知れません。
その時はすみません。
ツッコミお願いします!
情報はググッて仕入れてみます。
まず git clone
してみよう
git clone https://github.com/matsumoto-r/mod_vhost_maxclients.git
このような内容でした
-rw-r--r-- 1 kyswtnb staff 148 10 13 21:39 .clang-format drwxr-xr-x 12 kyswtnb staff 408 10 13 21:39 .git -rw-r--r-- 1 kyswtnb staff 112 10 13 21:39 .gitignore -rw-r--r-- 1 kyswtnb staff 6529 10 13 21:39 .travis.yml -rw-r--r-- 1 kyswtnb staff 175 10 13 21:39 LEGAL -rw-r--r-- 1 kyswtnb staff 1073 10 13 21:39 MITL -rw-r--r-- 1 kyswtnb staff 1293 10 13 21:39 Makefile -rw-r--r-- 1 kyswtnb staff 2224 10 13 21:39 README.md -rw-r--r-- 1 kyswtnb staff 12179 10 13 21:39 mod_vhost_maxclients.c drwxr-xr-x 13 kyswtnb staff 442 10 13 21:39 test
cで書かれているソースは mod_vhost_maxclients.c
これですね。
では読んでみましょう。
まず、apache関連のヘッダーファイルを取り込んでます。たぶん。
28 #include "httpd.h" 29 #include "http_config.h" 30 #include "http_request.h" 31 #include "http_protocol.h" 32 #include "http_core.h" 33 #include "http_log.h" 34 35 #include "ap_mpm.h" 36 #include "apr_strings.h" 37 #include "scoreboard.h"
これはわかるぞ!
モジュール名とバージョンですね。
39 #define MODULE_NAME "mod_vhost_maxclients" 40 #define MODULE_VERSION "0.3.2"
これは分からない。。
42 #if (AP_SERVER_MINORVERSION_NUMBER > 2) 43 #define __APACHE24__ 44 #endif
httpd-2.4.16.tar.gz
を落としてきて、grepしたら↓が書いてあった
#define AP_SERVER_MINORVERSION_NUMBER 4
#include
したヘッダーファイルの値を判定してるんですね。- 調べてみればわかるもんだ。
↑で定義した__APACHE24__
があったらさらに変数を定義
46 #ifdef __APACHE24__ 47 #define ap_get_scoreboard_worker ap_get_scoreboard_worker_from_indexes 48 #endif
そんな感じで、定義するところが続きます
50 #define _log_debug \ 51 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, "DEBUG: " MODULE_NAME "/" MODULE_VERSION "%s:%d", __func__, __LINE__) 52 53 #ifdef __APACHE24__ 54 #include "http_main.h" 55 #else 56 #define ap_server_conf NULL 57 #endif 58 59 #define VHOST_MAXEXTENSIONS 16 60 61 #if !defined(__APACHE24__) && defined(_WIN32) 62 /* 63 * libhttpd.dll does not export following variables. 64 * This won't work correctly, but working well for other functional. 65 */ 66 int ap_extended_status = 0; 67 #endif
windows,unix互換のマクロ AP_MODULE_DECLARE_DATA
を記述。たぶん。
69 module AP_MODULE_DECLARE_DATA vhost_maxclients_module;
スタティックな変数を宣言。同時に2つ宣言できるんですね。
70 static int vhost_maxclients_server_limit, vhost_maxclients_thread_limit;
構造体(変数の塊)を vhost_maxclients_config
という名前で定義している
72 typedef struct { 73 74 /* vhost max clinetns */ 75 int dryrun; 76 signed int vhost_maxclients; 77 signed int vhost_maxclients_per_ip; 78 apr_array_header_t *ignore_extensions; 79 80 } vhost_maxclients_config;
これがポインタ?
* apr_pool_t
bufferの保存場所?
* server_rec
apacheが持ってる構造体
* apr_pcalloc
メモリ領域を確保
* apr_array_make
配列を作成
ここでは、設定を読み込み領域を定義しているのかな〜と憶測
82 static void *vhost_maxclients_create_server_config(apr_pool_t *p, server_rec *s) 83 { 84 vhost_maxclients_config *scfg = (vhost_maxclients_config *)apr_pcalloc(p, sizeof(*scfg)); 85 86 scfg->dryrun = -1; 87 scfg->vhost_maxclients = 0; 88 scfg->vhost_maxclients_per_ip = 0; 89 scfg->ignore_extensions = apr_array_make(p, VHOST_MAXEXTENSIONS, sizeof(char *)); 90 91 return scfg; 92 }
ここも↑と同じで設定を読み込む構造体を定義しているように見える
94 static void* vhost_maxclients_create_server_merge_conf(apr_pool_t* p, void* b, void* n) 95 { 96 vhost_maxclients_config *base = (vhost_maxclients_config *)b; 97 vhost_maxclients_config *new = (vhost_maxclients_config *)n; 98 vhost_maxclients_config *scfg = (vhost_maxclients_config *)apr_pcalloc(p, sizeof(*scfg)); 99 100 if (new->dryrun > -1) { 101 scfg->dryrun = new->dryrun; 102 } else { 103 scfg->dryrun = base->dryrun; 104 } 105 scfg->vhost_maxclients = new->vhost_maxclients; 106 scfg->vhost_maxclients_per_ip = new->vhost_maxclients_per_ip; 107 scfg->ignore_extensions = new->ignore_extensions; 108 109 return scfg; 110 }
ちょっとここからは難しくなってきたので、仕切りなおしてまた次の日に・・・。
慣れだけなのだろうけど、ぱっとみて何やってるのか把握するのが難しい。
続けよう。