如何善用現有的library增快自己開發程式速度是現代工程師的課題,其實從我開始寫程式以來,大部份的動作,都是剪剪貼貼,看到不錯的演算法,就剪貼,看到能解決我問題的方案,也剪貼,我覺得只要能看得懂程式,就不算太嚴重的抄襲,甚至我可以補足這個程式某些沒有的功能,或加強程式的演算法,這些都能提昇我個人程設能力的credit
好了,廢話說太多了,這篇文章主要是介紹如何用c語言快速的寫出CGI程式,而我用的library就是大名鼎鼎的CGIC,這個library簡化了form與cgi溝通時所需要撰寫的複雜程序,工程師只要專注在不同type物件的name及value欄位即可
CGIC library使用方法非常簡單,下載完後,解開壓縮檔會看到兩個檔案分別是cgic.c和cgic.h,把它們跟你要寫的cgi程式擺在同一個資料夾下一起編譯即可,這邊舉個例子,假設我自寫的cgi檔名為test.c,則編譯時要下這樣的指令gcc –o test.cgi cgic.c test.c,test.c的內容如下範例
- #include <stdio.h>
- #include "cgic.h"
- #include <string.h>
- #include <stdlib.h>
- int cgiMain()
- {
- }
CGIC library提供很多的API,舉個例子,假設我今天要設定TextBox的值,並且讓cgi程式可把我設定的值印出來,那我的html表單可以設計如下
- <form method="post" enctype="multipart/form-data" action="http://192.168.15.26/cgi-bin/test.cgi">
- <p>Plaintext test:<input name="plaintext" size="80">
- </form>
而相對應的c程式可設計如下
- void handlePlainText()
- {
- char value[81];
-
- cgiFormStringNoNewlines("plaintext", value, 81);
- fprintf(cgiOut, "Plaintext test:: ");
- cgiHtmlEscape(value);
- fprintf(cgiOut, "<BR>\n");
- }
從上例可以看到,用了CGIC library,我要做的事就很簡單了,只要呼叫3個函式,一切搞定
OK,介紹完基本的,就講比較難一點cookie設定範例,我html表單設計如下
- <form method="post" enctype="multipart/form-data" action="http://192.168.15.26/cgi-bin/test.cgi">
- <p>Cookie test(not work on every browser):
- <p>Cookie Name:<input name="cname" value=""> <p>
- <p>Cookie Value:<input name="cvalue" value=""> <p>
- </form>
而c程式可簡單分為兩個function,一個是設定cookie,另外一個是顯示我們所設定的cookie
設定cookie
- void CookieSet()
- {
- char cname[1024];
- char cvalue[1024];
-
- cgiFormString("cname", cname, sizeof(cname));
- cgiFormString("cvalue", cvalue, sizeof(cvalue));
- if (strlen(cname))
- {
-
- cgiHeaderCookieSetString(cname, cvalue,86400, cgiScriptName, SERVER_NAME);
- }
- }
顯示我們所設定的cookie
- void Cookies()
- {
- char **array, **arrayStep;
- char cname[1024], cvalue[1024];
- fprintf(cgiOut, "Cookies Submitted On This Call, With Values (Many Browsers NEVER Submit Cookies):<p>\n");
- if (cgiCookies(&array) != cgiFormSuccess)
- {
- return;
- }
- arrayStep = array;
- fprintf(cgiOut, "<table border=1>\n");
- fprintf(cgiOut, "<tr><th>Cookie<th>Value</tr>\n");
- while (*arrayStep)
- {
- char value[1024];
- fprintf(cgiOut, "<tr>");
- fprintf(cgiOut, "<td>");
- cgiHtmlEscape(*arrayStep);
- fprintf(cgiOut, "<td>");
- cgiCookieString(*arrayStep, value, sizeof(value));
- cgiHtmlEscape(value);
- fprintf(cgiOut, "\n");
- arrayStep++;
- }
- fprintf(cgiOut, "</table>\n");
- }
不過我覺得CGIC library最強的API是上傳檔案的API,我下面這個範例會把上傳的檔案擺在/tmp資料夾,所以在執行前請確定cgi檔有root權限,html的表單設計如下,記得enctype一定要設為"multipart/form-data"
- <form method="post" enctype="multipart/form-data" action="http://192.168.15.26/cgi-bin/test.cgi">
- <p>File Upload:<input type="file" name="file" value=""> (Select A Local File)<p>
- </form>
而upload函式如下
- void File()
- {
- cgiFilePtr file;
- char name[1024];
- char contentType[1024];
- char buffer[1024];
- int size;
- int got;
- FILE *fp;
- char temp[256];
- int realwrite;
-
- if (cgiFormFileName("file", name, sizeof(name)) != cgiFormSuccess) {
- printf("<p>No file was uploaded.<p>\n");
- return;
- }
- fprintf(cgiOut, "The filename submitted was: ");
- cgiHtmlEscape(name);
- sprintf(temp,"touch /tmp/%s",name);
- system(temp);
- fprintf(cgiOut, "<p>\n");
- cgiFormFileSize("file", &size);
- fprintf(cgiOut, "The file size was: %d bytes<p>\n", size);
- cgiFormFileContentType("file", contentType, sizeof(contentType));
- fprintf(cgiOut, "The alleged content type of the file was: ");
- cgiHtmlEscape(contentType);
- fprintf(cgiOut, "<p>\n");
- if (cgiFormFileOpen("file", &file) != cgiFormSuccess)
- {
- fprintf(cgiOut, "Could not open the file.<p>\n");
- return;
- }
- fprintf(cgiOut, "<pre>\n");
-
- sprintf(temp,"/tmp/%s",name);
- fp=fopen(temp,"w");
-
- while (cgiFormFileRead(file, buffer, sizeof(buffer), &got) ==cgiFormSuccess)
- {
-
- fwrite(buffer,1,got,fp);
- //cgiHtmlEscapeData(buffer, got);
- //cgiHtmlEscapeData(buffer, got);
- }
- fclose(fp);
- fprintf(cgiOut, "</pre>\n");
- cgiFormFileClose(file);
- }
我所有的範例請下載這個壓縮包,裡面包含所有的CGIC library API的測試,測試畫面如下圖

Regular expression-跟brainfuck差不多的東西 (2009-11-13 15:37)
Reading file in kernel-簡單但實用 (2009-10-13 15:18)
Linux file system for dummies-只花你45分鐘 (2009-08-19 15:40)
OPENSSL-TCP SSL初心者之路 (2009-07-16 15:16)
NAPI與pure interrupt driver的效能比較 (2009-04-29 19:06)
usermode helper-來自kernel的呼喚 (2009-04-21 16:19)
kernel module memory detector-抓出有害的kernel module (2009-03-31 13:50)
kernel space coding-如履薄冰 (2009-03-26 09:52)
readahead與posix_advise-預讀取是萬能靈丹? (2009-03-06 15:54)