Webサーバ構築について
SH7706LSRボードに載せたLinux上でも、
前準備
SH7706LSRボードなどの組込みボードでWebサーバを構築する前に、
PC LinuxでのWebサーバ構築ではHTML文書の表示とともに、
一般的にはLinux上で計測や制御を行う場合はデバイスドライバを使うのが定番となっていますが、
CGIプログラム
HTMLのフォーム
単純にコンテンツを表示させるCGIプログラムならば、
HTML文書のタグにはCGIプログラムの動作を前提にしたフォームというタグの文法が定義されています。HTMLのフォームでは、
通常のプログラミング言語でのウィジェットではそのプログラミング言語だけで処理が閉じていてそれだけで完結していますが、
フォームとCGI
CGIプログラムは標準出力でHTML文書のコンテンツを出力するだけなので、
ただCGIプログラムは、
WebサーバにおいてHTMLのフォームの入力内容は環境変数を介して受け取ります。したがって、
Webサーバにおける環境変数
Webサーバでサポートする環境変数はいろいろとありますが、
- ① HTTP_
REFERER CGIプログラムを呼び出したリンク元のURLを取得することができます。CGIプログラムから元のページに戻る場合のリンクを設定する場合に用いると便利です。ただし、
CGIプログラムをブラウザで直接URL入力した場合とブックマークから呼び出した場合にNULLになります。 - ② HTTP_
USER_ AGENT ブラウザのバージョン番号とプラットフォーム名を含んだクライアントの情報を取得することができます。HTMLの標準的な機能以外の拡張機能はブラウザの種類によってサポート内容が異なったりするので、
クライアントにおけるブラウザの情報の内容に応じてCGIプログラムは臨機応変に対応することが可能になります。 - ③ REQUEST_
METHOD CGIプログラムへの要求方法を取得することができます。
- ④ QUERY_
STRING HTMLのフォームでのチェックボタンやラジオボタンなどのボタンによるユーザ入力やテキストボックスによるユーザが入力したテキスト内容を取得することができ、
CGIプログラムの動作に必須な環境変数となっています。 - ⑤ SCRIPT_
FILENAME CGIプログラムが置かれているマシンのフルパスでのファイル名を取得することができます。
- ⑥ SCRIPT_
NAME CGIプログラムが置かれているマシンでのhttpdのドキュメントルートからの相対パス名を取得することができます。
- ⑦ SERVER_
SOFTWARE httpdに関するソフトウェア情報を取得することができます。
CGIプログラムの実際
環境変数の表示
CGIプログラムの有機的に動作させる場合はCGIプログラムで環境変数の内容を取得することが必須になってきますので、
環境変数の内容を表示させるCGIプログラムのソースはリスト1となります。リスト1は、
1: #include <stdio.h>
2: #include <string.h>
3:
4: int main() {
5: printf("Content-type: text/html\n\n");
6: printf("<html><body bgcolor=peachpuff>\n");
7: printf("<div align=center><big>LEDOUT Control Page</big></div>\n");
8: printf("<hr size=2 width=100%>\n<p>\n");
9: printf("HTTP_REFER = %s<br>\n", getenv("HTTP_REFERER"));
10: printf("HTTP_USER_AGENT = %s<br>\n", getenv("HTTP_USER_AGENT"));
11: printf("QUERY_STRING = %s<br>\n", getenv("QUERY_STRING"));
12: printf("REQUEST_METHOD = %s<br>\n", getenv("REQUEST_METHOD"));
13: printf("SCRIPT_FILENAME = %s<br>\n", getenv("SCRIPT_FILENAME"));
14: printf("SCRIPT_NAME = %s<br>\n", getenv("SCRIPT_NAME"));
15: printf("SERVER_SOFTWARE = %s<br>\n", getenv("SERVER_SOFTWARE"));
16: printf("</body></html>\n");
17:
18: return 0;
19: }
リスト1のCGIプログラムを呼び出すフォームを含むHTML文書はリスト2となります。
1: <html><body bgcolor=peachpuff>
2: <div align=center><big>LEDOUT Control Page</big></div>
3: <hr size=2 width=100%>
4: <p>The on board LED on SH7706LSR.</p>
5: <form method="put" action="cgi-bin/ledout.cgi">
6: <p>
7: LEDOUT :
8: <input type="checkbox" name="ledout" value="on" /> ON <br>
9: <input type="submit" value="SUBMIT" />
10: <input type="reset" value="RESET" />
11: </p>
12: </form>
13: </body></html>
リスト2のフォームタグは5~12行目の部分となります。CGIプログラムを呼び出す部分は5行目で、
httpdのフォルダパスを/var/
# httpd -h /var/httpd
クライアントのブラウザからリスト2のHTML文書を表示させると、



フォーム情報の取得
今回はフォームのボタンの内容によりLEDの点滅を制御するCGIプログラムを作成しますが、
フォームタグでは複数のウィジェットを記述することができ、
URLにおいてはスペースが許されないので、
1: #include <stdio.h>
2: #include <string.h>
3:
4: int get_param(char *str) {
5: char *src, *dst;
6: int i, code;
7:
8: src = dst = str;
9: while(*src != 0) {
10: if(*src == '+') {
11: *dst++ = ' ';
12: } else if(*src == '%') {
13: code = 0;
14: for(i = 0;i < 2;i++) {
15: code <<= 4;
16: if(isdigit(src[i + 1])) code += src[i + 1] - '0';
17: else if(isupper(src[i + 1])) code += src[i + 1] - 'A' + 10;
18: else if(isdigit(src[i + 1])) code += src[i + 1] - 'a' + 10;
19: }
20: *dst++ = code;
21: src += 2;
22: } else {
23: *dst++ = *src;
24: }
25: src++;
26: }
27: *dst = 0;
28: }
29:
30: int main() {
31: char *param, *str;
32: int size;
33:
34: printf("Content-type: text/html\n\n");
35: printf("<html><body bgcolor=peachpuff>\n");
36: printf("<div align=center><big>LEDOUT Control Page</big></div>\n");
37: printf("<hr size=2 width=100%>\n");
38: printf("<p>The on board LED on SH7706LSR.</p>\n");
39:
40: str = getenv("QUERY_STRING");
41: size = strlen(str);
42: param = malloc(size + 1);
43: memcpy(param, str, size + 1);
44: str = strtok(param, "&=");
45: while(str != NULL) {
46: get_param(str);
47: printf("<p>%s ", str);
48: str = strtok(NULL,"&=");
49: get_param(str);
50: printf("%s</p>\n", str);
51: str = strtok(NULL,"&=");
52: }
53:
54: printf("<p><a href=%s>BACK</a></p>\n",getenv("HTTP_REFERER"));
55: printf("</body></html>\n");
56:
57: free(param);
58: return 0;
59: }
注意としては、
リスト3で、
リスト3のCGIプログラムでは、


CGIプログラムによるI/O制御
リスト3のCGIプログラムをベースにして、
1: #include <stdio.h>
2: #include <string.h>
3: #include <sys/types.h>
4: #include <sys/stat.h>
5: #include <fcntl.h>
6: #include <unistd.h>
7: #include <stdlib.h>
8: #include <stdio.h>
9: #include <string.h>
10: #include <sys/mman.h>
11: #include <asm/page.h>
12:
13: #define SCPDR 0x136
14: #define LED 0x10
15:
16: int get_param(char *str) {
17: char *src, *dst;
18: int i, code;
19:
20: src = dst = str;
21: while(*src != 0) {
22: if(*src == '+') {
23: *dst++ = ' ';
24: } else if(*src == '%') {
25: code = 0;
26: for(i = 0;i < 2;i++) {
27: code <<= 4;
28: if(isdigit(src[i + 1])) code += src[i + 1] - '0';
29: else if(isupper(src[i + 1])) code += src[i + 1] - 'A' + 10;
30: else if(isdigit(src[i + 1])) code += src[i + 1] - 'a' + 10;
31: }
32: *dst++ = code;
33: src += 2;
34: } else {
35: *dst++ = *src;
36: }
37: src++;
38: }
39: *dst = 0;
40: }
41:
42: int main() {
43: volatile unsigned char *mmaped, scpdr;
44: char *param, *str;
45: int fd, i, size;
46:
47: printf("Content-type: text/html\n\n");
48: printf("<html><body bgcolor=peachpuff>\n");
49: printf("<div align=center><big>LEDOUT Control Page</big></div>\n");
50: printf("<hr size=2 width=100%>\n");
51: printf("<p>The on board LED on SH7706LSR.</p>\n");
52: printf("<p><a href=%s>BACK</a></p>\n",getenv("HTTP_REFERER"));
53: printf("</body></html>\n");
54:
55: fd = open("/dev/mem",O_RDWR);
56: if(fd < 0) {
57: fprintf(stderr,"cannot open /dev/mem\n");
58: return -1;
59: }
60: mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xa4000000);
61: close(fd);
62: if(mmaped == MAP_FAILED) {
63: fprintf(stderr,"cannot mmap\n");
64: return -1;
65: }
66: str = getenv("QUERY_STRING");
67: size = strlen(str);
68: param = malloc(size + 1);
69: memcpy(param, str, size + 1);
70: str = strtok(param, "&=");
71:
72: mmaped[SCPDR] &= ~LED;
73:
74: while(str != NULL) {
75: get_param(str);
76: if(strcmp(str, "ledout") == 0) {
77: mmaped[SCPDR] |= LED;
78: }
79: str = strtok(NULL,"&=");
80: get_param(str);
81: str = strtok(NULL,"&=");
82: }
83: munmap((char*)mmaped, PAGE_SIZE);
84:
85: free(param);
86:
87: return 0;
88: }
リスト4のSH7706周辺制御レジスタを操作するための初期化処理は55~65行目となります。72行目では条件にかかわりなく一旦LEDを消灯させています。チェックボタンはチェックをした場合のみCGIプログラムへのパラメータとして有効となりますので、
リスト4のCGIプログラムはリスト1のHTML文書にあるフォームにより呼び出されるようになっていますが、
1: #include <stdio.h>
2: #include <string.h>
3: #include <sys/types.h>
4: #include <sys/stat.h>
5: #include <fcntl.h>
6: #include <unistd.h>
7: #include <stdlib.h>
8: #include <stdio.h>
9: #include <string.h>
10: #include <sys/mman.h>
11: #include <asm/page.h>
12:
13: #define SCPDR 0x136
14: #define LED 0x10
15:
16: int get_param(char *str) {
17: char *src, *dst;
18: int i, code;
19:
20: src = dst = str;
21: while(*src != 0) {
22: if(*src == '+') {
23: *dst++ = ' ';
24: } else if(*src == '%') {
25: code = 0;
26: for(i = 0;i < 2;i++) {
27: code <<= 4;
28: if(isdigit(src[i + 1])) code += src[i + 1] - '0';
29: else if(isupper(src[i + 1])) code += src[i + 1] - 'A' + 10;
30: else if(isdigit(src[i + 1])) code += src[i + 1] - 'a' + 10;
31: }
32: *dst++ = code;
33: src += 2;
34: } else {
35: *dst++ = *src;
36: }
37: src++;
38: }
39: *dst = 0;
40: }
41:
42: int main() {
43: volatile unsigned char *mmaped, scpdr;
44: char *param, *str;
45: int fd, i, size, flag;
46:
47: fd = open("/dev/mem",O_RDWR);
48: if(fd < 0) {
49: fprintf(stderr,"cannot open /dev/mem\n");
50: return -1;
51: }
52:
53: mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xa4000000);
54: close(fd);
55: if(mmaped == MAP_FAILED) {
56: fprintf(stderr,"cannot mmap\n");
57: return -1;
58: }
59: str = getenv("QUERY_STRING");
60: size = strlen(str);
61: param = malloc(size + 1);
62: memcpy(param, str, size + 1);
63: str = strtok(param, "&=");
64: mmaped[SCPDR] &= ~LED;
65: flag = 0;
66: while(str != NULL) {
67: get_param(str);
68: if(strcmp(str, "ledout") == 0) {
69: mmaped[SCPDR] |= LED;
70: flag = 1;
71: }
72: str = strtok(NULL,"&=");
73: get_param(str);
74: str = strtok(NULL,"&=");
75: }
76: munmap((char*)mmaped, PAGE_SIZE);
77: free(param);
78:
79: printf("Content-type: text/html\n\n");
80: printf("<html><body bgcolor=peachpuff>\n");
81: printf("<div align=center><big>LEDOUT Control Page</big></div>\n");
82: printf("<hr size=2 width=100%>\n");
83: printf("<p>The on board LED on SH7706LSR.</p>\n");
84: printf("<form method=put action=ledout.cgi>\n<p>\n");
85: printf("LEDOUT:<input type=checkbox name=ledout value=on ");
86: if(flag == 1) printf("checked");
87: printf(" /> ON <br>\n");
88: printf("<input type=submit value=SUBMIT />\n");
89: printf("<input type=reset value=RESET />\n</p>\n</form>\n");
90: printf("</body></html>\n");
91:
92: return 0;
93: }
1: #include <stdio.h>
2: #include <string.h>
3: #include <sys/types.h>
4: #include <sys/stat.h>
5: #include <fcntl.h>
6: #include <unistd.h>
7: #include <stdlib.h>
8: #include <stdio.h>
9: #include <string.h>
10: #include <sys/mman.h>
11: #include <asm/page.h>
12:
13: #define SCPDR 0x136
14: #define LED 0x10
15:
16: int get_param(char *str) {
17: char *src, *dst;
18: int i, code;
19:
20: src = dst = str;
21: while(*src != 0) {
22: if(*src == '+') {
23: *dst++ = ' ';
24: } else if(*src == '%') {
25: code = 0;
26: for(i = 0;i < 2;i++) {
27: code <<= 4;
28: if(isdigit(src[i + 1])) code += src[i + 1] - '0';
29: else if(isupper(src[i + 1])) code += src[i + 1] - 'A' + 10;
30: else if(isdigit(src[i + 1])) code += src[i + 1] - 'a' + 10;
31: }
32: *dst++ = code;
33: src += 2;
34: } else {
35: *dst++ = *src;
36: }
37: src++;
38: }
39: *dst = 0;
40: }
41:
42: int main() {
43: volatile unsigned char *mmaped, scpdr;
44: char *param, *str;
45: int fd, i, size, flag, ledparam;
46:
47: fd = open("/dev/mem",O_RDWR);
48: if(fd < 0) {
49: fprintf(stderr,"cannot open /dev/mem\n");
50: return -1;
51: }
52:
53: mmaped = (volatile unsigned char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0xa4000000);
54: close(fd);
55: if(mmaped == MAP_FAILED) {
56: fprintf(stderr,"cannot mmap\n");
57: return -1;
58: }
59: str = getenv("QUERY_STRING");
60: size = strlen(str);
61: param = malloc(size + 1);
62: memcpy(param, str, size + 1);
63: str = strtok(param, "&=");
64: while(str != NULL) {
65: get_param(str);
66: if(strcmp(str, "ledout") == 0) {
67: ledparam = 1;
68: } else {
69: ledparam = 0;
70: }
71: str = strtok(NULL,"&=");
72: get_param(str);
73: if(ledparam == 1) {
74: if(strcmp(str, "on") == 0) {
75: mmaped[SCPDR] |= LED;
76: flag = 1;
77: }
78: if(strcmp(str, "off") == 0) {
79: mmaped[SCPDR] &= ~LED;
80: flag = 0;
81: }
82: }
83: str = strtok(NULL,"&=");
84: }
85: munmap((char*)mmaped, PAGE_SIZE);
86: free(param);
87:
88: printf("Content-type: text/html\n\n");
89: printf("<html><body bgcolor=peachpuff>\n");
90: printf("<div align=center><big>LEDOUT Control Page</big></div>\n");
91: printf("<hr size=2 width=100%>\n");
92: printf("<p>The on board LED on SH7706LSR.</p>\n");
93: printf("<form method=put action=ledout.cgi>\n<p>\n");
94: printf("LEDOUT : <input type=radio name=ledout value=on ");
95: if(flag == 1) printf("checked");
96: printf(" /> ON ");
97: printf("<input type=radio name=ledout value=off ");
98: if(flag == 0) printf("checked");
99: printf(" /> OFF <br>\n");
100: printf("<input type=submit value=SUBMIT />\n");
101: printf("<input type=reset value=RESET />\n</p>\n</form>\n");
102: printf("</body></html>\n");
103:
104: return 0;
105: }

次回は
今回まではコンパイラ言語であるC言語でのプログラミングを扱ってきましたが、